Как сформировать длительный отчет в веб-клиенте 1С, чтобы страница браузера не зависала?

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

Работа в веб-клиенте 1С накладывает определенные ограничения на выполнение длительных серверных операций. Если отчет формируется дольше 30–60 секунд, браузер, не получая ответа от сервера, считает страницу «зависшей» и предлагает пользователю ее закрыть. Рассмотрим подробно, как решить эту проблему, используя механизмы асинхронности, фоновые задания и временные хранилища.

Почему возникает проблема в веб-клиенте?

Проанализируем ситуацию: когда вы запускаете формирование отчета напрямую из модуля формы, вызывая серверную процедуру, поток выполнения на клиенте (в браузере) блокируется. Он ожидает окончания работы сервера. У веб-серверов (IIS, Apache) и самих браузеров есть жесткие лимиты на время ожидания ответа. Как только лимит превышен, соединение может быть разорвано, а пользователь увидит сообщение «Страница не отвечает».

Шаг 1: Перенос логики из модуля формы

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

Проанализируем, что нужно передать в фоновое задание:

Шаг 2: Реализация формирования отчета в модуле менеджера

Рассмотрим пример процедуры, которую мы разместим в модуле менеджера отчета. Эта процедура будет выполняться в фоне.


Процедура СформироватьОтчетДляФона(ПараметрыОтчета, АдресХранилища) Экспорт
    
    ТабДок = Новый ТабличныйДокумент;
    
    // Здесь размещаем ваш запрос и логику вывода данных
    // Например, программный вывод СКД:
    ОтчетОбъект = Отчеты.МойСамописныйОтчет.Создать();
    ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(ПараметрыОтчета.Настройки);
    
    ОтчетОбъект.СкомпоноватьРезультат(ТабДок);
    
    // Помещаем готовый табличный документ в хранилище по переданному адресу
    ПоместитьВоВременноеХранилище(ТабДок, АдресХранилища);
    
КонецПроцедуры

Шаг 3: Запуск фонового задания из формы

Теперь выясним, как правильно инициировать процесс с клиента. Нам понадобится уникальный идентификатор формы, чтобы данные в хранилище «жили» до тех пор, пока форма открыта.

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


&НаКлиенте
Процедура СформироватьОтчет(Команда)
    
    // 1. Создаем адрес во временном хранилище
    АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, ЭтаФорма.УникальныйИдентификатор);
    
    // 2. Готовим параметры для передачи на сервер
    ПараметрыОтчета = Новый Структура;
    ПараметрыОтчета.Вставить("Настройки", Отчет.КомпоновщикНастроек.ПолучитьНастройки());
    
    // 3. Запускаем фоновое задание
    РезультатЗапуска = ЗапуститьВыполнениеНаСервере(ПараметрыОтчета, АдресХранилища);
    
    ИдентификаторЗадания = РезультатЗапуска.ИдентификаторЗадания;
    
    // 4. Подключаем обработчик ожидания, чтобы проверять готовность
    ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания", 2, Ложь);
    
    Состояние("Отчет формируется, подождите...");
    
КонецПроцедуры

Шаг 4: Использование обработчика ожидания

Это критически важный этап для веб-клиента. Вместо того чтобы ждать ответа в одной длительной транзакции, мы «отпускаем» браузер и просим его заходить за результатом каждые 2 секунды. Это сохраняет отзывчивость интерфейса. Для реализации такого сценария подойдёт пример отслеживания фоновых заданий без БСП.


&НаКлиенте
Процедура Подключаемый_ПроверитьВыполнениеЗадания()
    
    Если ЗаданиеЗавершено(ИдентификаторЗадания) Тогда
        
        ОтключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания");
        
        // Получаем результат из хранилища
        РезультатТабДок = ПолучитьИзВременногоХранилища(АдресХранилища);
        
        // Выводим на форму (в реквизит типа ТабличныйДокумент)
        Результат.Вывести(РезультатТабДок);
        
        Состояние("Формирование завершено");
        
    КонецЕсли;
    
КонецПроцедуры

Шаг 5: Использование БСП (Библиотека стандартных подсистем)

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

Разберем, как это выглядит с БСП:

  1. Вызываем ДлительныеОперации.ЗапуститьВыполнениеНаСервере(). Она сама создаст фоновое задание.
  2. Используем ДлительныеОперацииКлиент.ОжидатьЗавершение(), которая откроет стандартное окно ожидания с «котиком» или прогресс-баром.
  3. По завершении вызываем ДлительныеОперации.ПолучитьРезультатВыполнения().

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

Шаг 6: Настройка веб-сервера

Даже при использовании фоновых заданий, иногда требуется подправить настройки самого веб-сервера. Проанализируем основные параметры:

Для IIS: В файле web.config проверьте параметр requestTimeout. Если он слишком мал, веб-сервер может обрывать даже короткие запросы проверки статуса при высокой нагрузке.

Для Nginx (реверс-прокси): Если 1С опубликована через Nginx, необходимо увеличить таймауты в конфигурационном файле:

Подведем итоги

Чтобы отчет в веб-клиенте перестал «вешать» страницу, мы выполнили следующие действия: вынесли расчет в модуль менеджера, запустили фоновое задание, организовали обмен через временное хранилище и внедрили циклический опрос сервера через обработчик ожидания. Такой подход гарантирует, что браузер будет считать страницу активной, а пользователь сможет дождаться результата даже самого тяжелого отчета.

← На главную