Приветствую Вас ГостьСуббота, 18.05.2024, 14:32

Каталог статей


Асинхронные методы (процедуры и функции)

После отказа от модальных форм был реализован механизм немодального вызова методов. 

Примеры аналогов:

Синхронный метод  Асинхронная процедура, использующая метод обратного вызова  Асинхронная функция, возвращающая Обещание
Вопрос     ПоказатьВопрос     ВопросАсинх
Предупреждение     ПоказатьПредупреждение     ПредупреждениеАсинх
ОткрытьЗначение     ПоказатьЗначение     ОткрытьЗначениеАсинх
КопироватьФайл     НачатьКопированиеФайла     КопироватьФайлАсинх
ВвестиЧисло     ПоказатьВводЧисла     ВвестиЧислоАсинх
НайтиФайлы     НачатьПоискФайлов     НайтиФайлыАсинх
ПолучитьФайл     НачатьПолучениеФайлаССервера     ПолучитьФайлССервераАсинх

Метод обратного вызова (использование оповещений)

(основной материал взят с https://its.1c.ru/docs/v8nonmodal/#24)

Если не требуется немедленный ответ в процедуре/функции, то используется метод со словом "Показать", в котором указывается описание оповещения. В описании оповещения задается экспортная клиентская процедура, которая будет выполняться после получения ответа со стороны пользователя. Например:

Таким образом алгоритм, который раньше являлся одним целым, теперь нужно разделять на две части. Одна часть открывает блокирующее окно. Вторая часть обрабатывает реакцию пользователя в блокирующем окне. Чтобы система знала, с какого места продолжать исполнение программного кода, блокирующему окну передаётся имя процедуры, которая должна быть выполнена тогда, когда пользователь закроет это окно.

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

Если кроме результата во вторую часть алгоритма надо передать дополнительные данные, то в описании оповещения указываем структуру параметров, которые будут выгружены во второй параметр ("ДополнительныеПараметры") экспортной процедуры.

Если после вызова вложенной функции выполнятся некоторый код, то в такой ситуации нужно не только использовать блокирующий метод с вызовом оповещения, но ещё и выполнять асинхронный вызов самой вложенной процедуры, также используя оповещение:

Вопрос в обработчике формы ПередЗакрытием

Этот случай вызывает некоторые трудности: в зависимости от реакции пользователя принимается решение: продолжать дальнейшие действия, или отказаться от них. Для этого используется параметр процедуры Отказ. При одном ответе пользователя мы отказываемся от продолжения (Отказ = Истина). При другом ответе пользователя - продолжаем дальнейшие действия.

В данном случае сложность заключается в том, что ответ пользователя мы узнаем уже после того, как выйдем из контекста этого обработчика. В процедуре, обрабатывающей оповещение. А параметр Отказ нужно установить именно в этом обработчике.

Поэтому мы действуем в два приёма:

  • В первый раз безусловно отменяем дальнейшие действия (Отказ = Истина) и выводим вопрос пользователю;
  • В обработчике оповещения, в зависимости от реакции пользователя, либо снова программно закрываем форму, либо ничего не делаем.

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

В первый проход её значение равно Ложь, и это значит, что нужно отказаться от закрытия и задать вопрос. Во второй проход её значение равно Истина, и это значит, что вопрос задавать не надо:

Обратите внимание на то, что переменная ВыполняетсяЗакрытие объявлена на клиенте.

Вопрос в обработчике формы ПередЗаписью

В обработчике события формы ПередЗаписью также может возникнуть потребность задать вопрос. Как и в предыдущем примере. Однако здесь вопрос так просто не решается. Отличие заключается в следующем.

В предыдущем примере, оказываясь в обработчике ПередЗакрытием, мы однозначно знали действие, которое должно быть выполнено. Это закрытие формы. Поэтому в обработке оповещения мы смело писали Закрыть().

Но в обработчике ПередЗаписью мы такой однозначной информации не имеем. В этом обработчике мы можем оказаться по двум причинам: если пользователь нажал Записать, или если он нажал Записать и закрыть.

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

В экспортной процедуре в конце добавим код:

   Если ДополнительныеПараметры.ЗакрытьФорму Тогда
            Закрыть(ДополнительныеПараметры);
        Иначе
            ЗаписатьДокументНаСервере();                
   КонецЕсли;

Если была нажата кнопка "Провести и закрыть" или "Записать и закрыть", то значение ЗакрытьФорму = Истина, и мы выполняем метод Закрыть, в который передаем параметр ПараметрыЗаписи, которые находятся в ДополнительныеПараметры. Если была нажата кнопка "Записать", то записываем документ без закрытия формы.

Работа с асинхронными функциями

Асинхронная функция возвращает значение типа Обещание. Чтобы из этого значения получить результат работы асинхронной функции, нужно воспользоваться оператором Ждать, который также появился в платформе 8.3.18. Единственным параметром оператора Ждать является объект типа Обещание:

Результат = Ждать Обещание;

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

Результат = Ждать 1000;

Этот код установит в переменную Результат значение 1000, а не будет ждать 1000 миллисекунд.

Проблема в том, что если не использовать Ждать, то процедура продолжить свое выполнение не дожидаясь ответа.

Оператор Ждать можно поставить только в процедуре/функции, у которой стоит модификатор "Асинх", т.е. нельзя выполнить код:

Процедура Тест()

   Ответ = Ждать ВопросАсинх(...)

КонецПроцедуры

Должно быть так:

Асинх Процедура Тест()

   Ответ = Ждать ВопросАсинх(...)

КонецПроцедуры

Если процедуру Тест выполним не из асинхронной процедуры, то процедура продолжит свое выполнение после вызова  Тест()

Процедура ПредТест()

   Тест();

   Сообщить("Продолжить выполнение");

КонецПроцедуры

Чтобы выполнить метод Сообщить("Продолжить выполнение"); после получения ответа на вопрос, надо перед процедурой Тест() поставить оператор Ждать, т.е. для процедуры ПредТест() надо тоже поставить модификатор "Асинх".

Получается замкнутый круг.

Для решения этой проблемы надо либо использовать клиентскую переменную в качестве флага, по аналогии с методом обратного вызова, либо главную процедуру, например обработчик события, сразу снабдить модификатором "Асинх", например:

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

Категория: Формы | Добавил: leshic (30.11.2021)
Просмотров: 1908 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Вход на сайт
Поиск
Категории раздела
СКД [48]
Регистры [7]
Формы [41]
Администрирование [35]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [29]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0