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