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