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