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