Как задать вопрос пользователю в веб-клиенте 1С и обработать ответ в общем модуле

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

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

Почему старый метод Вопрос() больше не подходит

Разберем причину возникновения проблемы. В веб-клиенте выполнение кода не может «замереть» на строке с вопросом и ждать, пока пользователь нажмет кнопку «Да» или «Нет». Если бы это произошло, вкладка браузера просто зависла бы. Поэтому платформа требует использования асинхронных вызовов. Это означает, что процедура должна завершиться сразу после вызова окна вопроса, а обработка результата должна происходить в другой, специально выделенной процедуре. Если же работу в интерфейсе нужно автоматизировать без создания сложных сценариев, применяется платформа One RPA для создания программных роботов.

Способ 1. Использование ОписанияОповещения и ПоказатьВопрос

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

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


// Основная процедура, которая инициирует вопрос
Процедура НачалоПечати(ПараметрыПечати) Экспорт

    // Формируем описание оповещения, указывая, куда вернуться после ответа
    Оповещение = Новый ОписаниеОповещения("ЗавершениеПечатиПослеВопроса", ЭтотОбъект, ПараметрыПечати);
    
    ТекстВопроса = НСтр("ru = 'Выполнить печать с дополнительными настройками?'");
    Кнопки = РежимДиалогаВопрос.ДаНет;
    
    // Вызываем неблокирующее окно вопроса
    ПоказатьВопрос(Оповещение, ТекстВопроса, Кнопки);
    
    // ВАЖНО: Код ниже этой строки выполнится СРАЗУ, не дожидаясь ответа.
    // Поэтому здесь не должно быть логики, зависящей от выбора пользователя.
КонецПроцедуры

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

КонецПроцедуры

Рассмотрим подробнее параметры ОписаниеОповещения. Первый параметр — это имя процедуры, которая будет вызвана после нажатия кнопки. Второй параметр — контекст (обычно ЭтотОбъект). Третий параметр позволяет «пробросить» любые данные из первой процедуры во вторую, чтобы не потерять состояние расчетов.

Способ 2. Современный подход через Асинх и Ждать (платформа 8.3.18+)

Если ваша конфигурация работает на платформе версии 8.3.18 и выше, мы можем использовать гораздо более элегантный способ, который позволяет писать код почти так же, как раньше — линейно. Это достигается с помощью механизмов Асинх и Ждать.

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


&НаКлиенте
Асинх Процедура ВыполнитьПечатьСВопросом(Параметры)
    
    ТекстВопроса = "Продолжить формирование печатной формы?";
    
    // Код «замирает» на этой строке до получения ответа, 
    // но при этом не блокирует интерфейс браузера.
    Результат = Ждать ВопросАсинх(ТекстВопроса, РежимДиалогаВопрос.ДаНет);
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        // Мы продолжаем работать в той же самой процедуре!
        // Все локальные переменные сохранены.
        ЗапуститьГенерациюОтчета(Параметры);
    КонецЕсли;
    
КонецПроцедуры

Преимущества этого метода:

  1. Код остается целостным и легко читаемым.
  2. Нет необходимости создавать десятки вспомогательных процедур типа «Продолжение...».
  3. Переменные и контекст сохраняются автоматически внутри одной области видимости.

Способ 3. Рекурсивный вызов с флагом состояния

Иногда возникают ситуации, когда архитектура типового модуля (например, в БСП) сильно ограничивает нас в создании новых экспортных процедур. В этом случае можно использовать прием «повторного входа».

Рассмотрим ситуацию: у нас есть одна точка входа. Мы можем передать в параметрах специальный флаг ОтветПолучен. Если он ложный — задаем вопрос. В качестве обработчика оповещения указываем эту же самую процедуру, но в параметрах передаем флаг Истина и результат выбора.


Процедура УниверсальнаяПечать(Параметры, ОтветПолучен = Ложь, РезультатВопроса = Неопределено) Экспорт

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

    // Сюда мы попадем только при втором вызове (из оповещения)
    Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
        // Логика исполнения
    КонецЕсли;

КонецПроцедуры

Рекомендации по реализации в типовых решениях (БСП)

Поскольку модуль УправлениеПечатьюКлиент является частью Библиотеки Стандартных Подсистем (БСП), при внесении изменений нужно придерживаться определенных правил, чтобы не нарушить обновление конфигурации:

Подводя итог, отметим: переход к асинхронности в веб-клиенте — это не прихоть разработчиков платформы, а техническая необходимость веб-среды. Использование ВопросАсинх является наиболее перспективным методом, в то время как ОписаниеОповещения остается надежным стандартом для поддержки старых версий систем.

← На главную