Как исправить ошибку «Использование модальных окон запрещено» в 1С 8.3 и перейти на асинхронные вызовы

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки или обновления конфигураций на платформе 1С:Предприятие 8.3 многие программисты сталкиваются с критической ошибкой: Использование модальных окон запрещено. Эта проблема особенно актуальна при переходе с обычных форм на управляемые или при попытке запустить старый код в веб-клиенте. Рассмотрим подробнее, почему возникло это ограничение, и разберем по шагам, как переписать код так, чтобы он соответствовал современным стандартам платформы.

Выясним причину возникновения ошибки

Причина кроется в архитектурных изменениях платформы. Модальные окна (такие как Вопрос(), Предупреждение(), ОткрытьФормуМодально()) полностью блокируют работу всего приложения и всех его вкладок до тех пор, пока пользователь не закроет окно. В современных браузерах и веб-технологиях такая блокировка считается плохой практикой и часто блокируется самими браузерами.

Для обеспечения стабильной работы в веб-клиенте и повышения отзывчивости интерфейса, компания «1С» ввела запрет на модальность. Проанализируем ситуацию: если в свойствах вашей конфигурации параметр Режим использования модальности установлен в значение Не использовать, любой вызов модального метода приведет к аварийному завершению процедуры. Нам необходимо перевести интерфейсные взаимодействия в асинхронный режим.

Настройка конфигурации перед началом работы

Прежде чем приступать к написанию кода, проверим настройки самой базы. Если вы занимаетесь глубокой реструктуризацией старой системы, у вас есть два пути:

  1. Временный (не рекомендуемый): Изменить свойство конфигурации «Режим использования модальности» на Использовать. Это позволит старому коду работать, но сделает невозможной полноценную работу в браузере.
  2. Правильный: Оставить режим Не использовать и внедрить механизм Описания оповещений. Это обеспечит кроссплатформенность и готовность к работе в облачных сервисах.

Разберем основной инструмент: Объект ОписаниеОповещения

Ключевым объектом для замены модальности является ОписаниеОповещения. Посмотрим на его структуру. Этот объект указывает платформе, какую процедуру нужно выполнить после того, как пользователь совершит действие в диалоговом окне (нажмет кнопку, выберет файл и т.д.).

Конструктор объекта выглядит следующим образом:

Новый ОписаниеОповещения("<ИмяПроцедуры>", <Модуль>, <ДополнительныеПараметры>);

Где <ИмяПроцедуры> — это строка с названием экспортной процедуры, которая примет результат выбора пользователя.

Решение 1: Замена функции Вопрос()

Рассмотрим пример. Раньше мы писали синхронный код, который ждал ответа пользователя прямо в месте вызова:


Ответ = Вопрос("Продолжить выполнение операции?", РежимДиалога.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
    // Основная логика
КонецЕсли;

В новом режиме работы нам нужно разделить этот алгоритм на две части. Проанализируем новый подход:

Шаг 1: Вызов диалога


&НаКлиенте
Процедура НачатьВыполнениеОперации(Команда)
    
    Оповещение = Новый ОписаниеОповещения("ЗавершитьВыполнениеОперации", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, "Продолжить выполнение операции?", РежимДиалога.ДаНет);
    
КонецПроцедуры

Шаг 2: Обработка результата в отдельной процедуре


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

Решение 2: Замена метода ОткрытьФормуМодально()

Работа с формами также претерпела изменения. Вместо блокирующего вызова ОткрытьФормуМодально() мы должны использовать ОткрытьФорму() с передачей описания оповещения о закрытии.

Посмотрим на пример открытия формы подбора товаров:


&НаКлиенте
Процедура ВыбратьТовары(Команда)
    
    ПараметрыОповещения = Новый ОписаниеОповещения("ПослеПодбораТоваров", ЭтотОбъект);
    ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", , ЭтаФорма, , , , ПараметрыОповещения);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеПодбораТоваров(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    Если ЗначениеЗаполнено(РезультатВыбора) Тогда
        // Обработка выбранного элемента
        Сообщить("Выбран товар: " + РезультатВыбора);
    КонецЕсли;
    
КонецПроцедуры

Использование дополнительных параметров

Часто в процедуру обработки результата (callback) нужно передать контекст — данные, которые были доступны в исходной процедуре. Для этого используется третий параметр конструктора ОписаниеОповещения.

Разберем ситуацию, когда нам нужно передать структуру данных:


&НаКлиенте
Процедура ПроверитьСтатус(Команда)
    
    Контекст = Новый Структура;
    Контекст.Вставить("ИмяТекущегоОбъекта", "ДокументПродажи");
    Контекст.Вставить("ДатаНачала", ТекущаяДата());
    
    Оповещение = Новый ОписаниеОповещения("ОбработатьОтветСтатуса", ЭтотОбъект, Контекст);
    ПоказатьВопрос(Оповещение, "Изменить статус?", РежимДиалога.ОКОтмена);
    
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьОтветСтатуса(Результат, ДополнительныеПараметры) Экспорт
    
    // ДополнительныеПараметры теперь содержат нашу структуру
    Если Результат = КодВозвратаДиалога.ОК Тогда
        Сообщить("Работаем с объектом: " + ДополнительныеПараметры.ИмяТекущегоОбъекта);
    КонецЕсли;
    
КонецПроцедуры

Важные особенности асинхронной разработки

Проанализируем ключевые моменты, которые нужно учитывать, чтобы избежать логических ошибок при отказе от модальности:

Типичные ошибки при переходе

Рассмотрим распространенные ошибки программистов 1С:

  1. Использование серверных процедур в оповещении: Процедура обработки результата должна быть &НаКлиенте. Сервер не может напрямую взаимодействовать с интерактивными окнами пользователя.
  2. Потеря контекста: Если вы забыли передать важные переменные через ДополнительныеПараметры, в процедуре оповещения они будут недоступны, так как стек вызовов основной процедуры уже будет завершен.
  3. Бесконечные циклы: Нельзя использовать асинхронные вызовы внутри обычных циклов Для или Для Каждого, если вы хотите "остановить" цикл до ответа. В таких случаях цикл нужно реализовывать через рекурсивный вызов процедур оповещения.

Подведем итог: переход от модальности к асинхронности требует изменения архитектурного мышления. Вместо линейного кода мы строим событийно-ориентированную модель. Использование объектов ОписаниеОповещения и методов семейства Показать... (например, ПоказатьПредупреждение, ПоказатьВводЗначения) делает вашу конфигурацию современной, быстрой и совместимой со всеми вариантами клиентских приложений 1С.

← На главную