При интеграции 1С с внешними веб-сервисами разработчики часто сталкиваются с ситуацией, когда запрос к серверу уже отправлен, но результат будет готов лишь спустя неопределенное время. Типичный пример — запрос на формирование тяжелого отчета, обработка большого массива данных или взаимодействие с государственными информационными системами. В таких случаях прямое ожидание в коде (синхронный вызов) приведет к «зависанию» интерфейса пользователя, что недопустимо в современной разработке. Рассмотрим подробнее, какие инструменты предоставляет платформа 1С для решения этой задачи, начиная от классических методов и заканчивая современными асинхронными возможностями.
Самый распространенный и надежный способ — использование метода ПодключитьОбработчикОжидания. Однако основная трудность, с которой сталкиваются программисты, — невозможность напрямую передать параметры в процедуру-обработчик. Выясним причину: обработчик вызывается платформой в глобальном контексте формы, и его сигнатура строго определена. Чтобы обойти это ограничение, проанализируем ситуацию с хранением состояния.
Для того чтобы не «засорять» реквизиты формы множеством переменных (токен, адрес запроса, количество попыток), рекомендуется использовать структуру-контейнер. Разберем по шагам, как организовать хранение данных через Временное хранилище с привязкой к уникальному идентификатору формы:
УникальныйИдентификатор текущей формы. Это гарантирует, что данные будут жить ровно столько, сколько открыта форма.Посмотрим на пример реализации этой логики:
// В процедуре, инициирующей запрос
КонтекстЗапроса = Новый Структура;
КонтекстЗапроса.Вставить("Токен", ПолученныйТокен);
КонтекстЗапроса.Вставить("АдресЗапроса", "https://api.service.ru/getResult");
КонтекстЗапроса.Вставить("Попытка", 1);
АдресХранилища = ПоместитьВоВременноеХранилище(КонтекстЗапроса, ЭтаФорма.УникальныйИдентификатор);
// Подключаем обработчик на каждые 5 секунд
ПодключитьОбработчикОжидания("ПроверитьСтатусЗапроса", 5);
В самой процедуре ПроверитьСтатусЗапроса мы анализируем ответ и принимаем решение: продолжить ожидание или завершить его. Важный момент: не забудьте вызвать ОтключитьОбработчикОжидания, как только результат получен или превышено количество попыток.
Если опрос сайта должен происходить в фоновом режиме, не мешая пользователю работать в других окнах или даже если форма будет закрыта, стоит рассмотреть использование фоновых заданий. В современных конфигурациях на базе БСП (Библиотека стандартных подсистем) для этого существует мощный инструмент — подсистема «Длительные операции».
Проанализируем преимущества этого подхода. Вместо того чтобы «дергать» сервер с клиента, мы запускаем фоновое задание на сервере 1С. Это задание само выполняет цикл ожидания. Для реализации паузы внутри фонового задания на сервере (начиная с версии 8.3.15) рекомендуется использовать метод ФоновоеЗадание.ОжидатьЗавершенияВыполнения() или механизмы БСП.
Рассмотрим, как реализовать паузу на сервере правильно, не прибегая к «грязным» хакам типа бесконечных циклов:
// Пример функции для паузы на сервере (внутри фонового задания)
Процедура ВыполнитьПаузу(Секунд) Экспорт
Если Секунд > 0 Тогда
Задание = ФоновыеЗадания.Выполнить("ОбщегоНазначения.ПустаяПроцедура");
Попытка
Задание.ОжидатьЗавершения(Секунд);
Исключение
// Тайм-аут - это штатная ситуация для паузы
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Этот способ позволяет серверному процессу эффективно «спать», освобождая ресурсы процессора для других задач, в отличие от пустых циклов Пока...КонецЦикла.
Выясним, что изменилось в последних версиях платформы. 1С активно внедряет механизмы Promise-подобного взаимодействия. В версии 8.3.21 появились асинхронные HTTP-запросы. Теперь мы можем использовать ключевое слово Ждать (Await), что делает код линейным и легко читаемым.
Разберем пример того, как это выглядит в современном стиле:
&НаКлиенте
Асинхронная Процедура ВыполнитьЗапросАсинхронно()
Соединение = Новый HTTPСоединение("api.site.com");
Запрос = Новый HTTPЗапрос("/data");
// Интерфейс не блокируется в момент ожидания!
Ответ = Ждать Соединение.ВызватьHTTPМетодАсинх ("GET", Запрос);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Данные получены!");
КонецЕсли;
КонецПроцедуры
Важное примечание: этот метод доступен только на клиенте. Он идеально подходит для интерактивных форм, когда нам нужно дождаться ответа от сайта, сохранив отзывчивость интерфейса (пользователь может нажимать другие кнопки, изменять данные в таблицах), при этом контекст процедуры (локальные переменные) сохраняется автоматически.
Когда запросов очень много, и они могут выполняться минутами, лучшим архитектурным решением будет использование Регистра сведений. Разберем этот паттерн:
Токен, ДатаЗапроса, Статус (Ожидает).ПодключитьОбработчикОжидания просто проверяет статус записи в регистре по своему токену.Такой подход максимально отказоустойчив. Даже если у пользователя пропадет интернет или сеанс 1С завершится аварийно, сервер закончит обработку данных и сохранит результат, который будет доступен при следующем открытии формы.
Выберем подходящий вариант в зависимости от условий задачи:
Проанализировав все способы, мы видим, что платформа 1С эволюционировала от простых таймеров к полноценной асинхронной модели. Выбор конкретного метода должен основываться на версии вашей платформы и требованиях к надежности хранения результата.