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