Как вернуть результат и продолжить выполнение кода при использовании ОписаниеОповещения в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе на работу в режиме без использования модальности многие разработчики сталкиваются с принципиальным изменением парадигмы выполнения кода. В классическом синхронном коде вызов диалога (например, метода Вопрос) приостанавливал выполнение функции, ожидал нажатия кнопки пользователем и возвращал результат напрямую в переменную. При переходе на немодальные методы (такие как ПоказатьВопрос) функция не останавливается, а сразу завершает свое выполнение. Разберем, как правильно выстраивать логику алгоритмов и передавать контекст при асинхронной модели разработки в платформе 1С:Предприятие 8.3.

Принцип работы механизма немодальности через ОписаниеОповещения

Проанализируем ключевое отличие асинхронного подхода: метод ПоказатьВопрос не возвращает значение в ту же строку, где был вызван. Вместо этого он принимает объект ОписаниеОповещения, инициализирует диалоговое окно и мгновенно отдает управление дальше. Исходная процедура или функция завершает работу до того, как пользователь сделает выбор.

Посмотрим на правила обработки ответа пользователя:

  1. Ответ пользователя передается первым параметром в процедуру-обработчик, имя которой указано в конструкторе ОписаниеОповещения.
  2. Вернуться в стек вызова исходной процедуры невозможно, так как она уже отработала. Вся дальнейшая бизнес-логика (проверки, проведение документов, открытие форм) должна продолжаться внутри процедуры-обработчика.
  3. Все переменные исходной процедуры уничтожаются после ее завершения, поэтому любые данные контекста необходимо явно передавать через структуру дополнительных параметров.

Передача контекста через ДополнительныеПараметры

Рассмотрим, как связать исходный контекст с процедурой-обработчиком. Для сохранения промежуточных вычислений сформируем структуру и передадим ее третьим параметром конструктора ОписаниеОповещения.

Разберем по шагам реализацию данного паттерна:


&НаКлиенте
Процедура ЗапуститьОбработкуДанных()
    
    ПараметрыОповещения = Новый Структура;
    ПараметрыОповещения.Вставить("ИдентификаторЗадачи", 1024);
    ПараметрыОповещения.Вставить("СуммаДокумента", 150000);
    
    Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект, ПараметрыОповещения);
    
    ПоказатьВопрос(Оповещение, "Сумма превышает лимит. Продолжить проведение?", РежимДиалогаВопрос.ДаНет);
    
    // Исходная процедура завершается здесь, не дожидаясь ответа пользователя
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеОтветаНаВопрос(РезультатВопроса, ДополнительныеПараметры) Экспорт
    
    Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
        
        Идентификатор = ДополнительныеПараметры.ИдентификаторЗадачи;
        Сумма = ДополнительныеПараметры.СуммаДокумента;
        
        // Продолжаем выполнение бизнес-логики с переданными данными
        ВыполнитьПроведениеНаСервере(Идентификатор, Сумма);
        
    КонецЕсли;
    
КонецПроцедуры

Современная альтернатива: асинхронные функции и оператор Ждать (начиная с 8.3.18)

В современных версиях платформы реализован механизм асинхронных процедур и функций с ключевыми словами Асинх и Ждать. Это позволяет писать линейный и легко читаемый код без создания вспомогательных процедур обратного вызова.

Посмотрим на пример использования асинхронного диалога:


&НаКлиенте
Асинх Процедура ПроверитьИЗаписатьДокумент()
    
    // Выполнение приостанавливается до выбора пользователя, затем результат возвращается в переменную
    Ответ = Ждать ВопросАсинх("Записать изменения в базу данных?", РежимДиалогаВопрос.ДаНет);
    
    Если Ответ = КодВозвратаДиалога.Да Тогда
        
        // Линейное продолжение кода в рамках того же контекста
        ЭтотОбъект.Записать();
        
    КонецЕсли;
    
КонецПроцедуры

Обработка диалогов в стандартных событиях форм

Особую сложность представляют стандартные события форм, такие как ПередЗаписью или ПередЗакрытием. Если в них вызвать асинхронный диалог, платформа закроет или запишет форму еще до того, как пользователь успеет нажать кнопку в окне диалога.

Разберем стандартный алгоритм обхода этой проблемы:

  1. В обработчике события проверяем служебный флаг (например, переменную модуля формы или реквизит формы).
  2. Если подтверждение еще не получено, прерываем стандартное действие: устанавливаем Отказ = Истина или СтандартнаяОбработка = Ложь.
  3. Запускаем показ диалога через ОписаниеОповещения или асинхронный вызов.
  4. В обработчике ответа, если пользователь согласился, устанавливаем флаг в значение Истина и программно вызываем требуемый метод формы (Записать() или Закрыть()). При повторном входе в событие проверка флага позволит операции выполниться штатно.

Важные требования и ограничения платформы

Выясним ключевые технические нюансы, которые необходимо соблюдать при разработке немодальных интерфейсов:

Экспортность процедур: процедура-обработчик оповещения обязательно должна быть объявлена с директивой Экспорт, если она располагается в общем модуле, модуле команды или внешней форме.

Контекст выполнения: если в качестве модуля обработки передан объект формы (ЭтотОбъект), а форма была закрыта пользователем до завершения фоновой или асинхронной операции, вызов процедуры-обработчика вызовет исключение потери контекста. Для длительных глобальных операций целесообразно выносить обработчики в общие клиентские модули.

Режим модальности: если в свойствах конфигурации параметр РежимИспользованияМодальности выставлен в значение НеИспользовать, любой вызов синхронных модальных методов (Вопрос, Предупреждение, ВвестиЗначение) приведет к аварийному завершению с ошибкой времени выполнения.

← На главную