При выполнении длительных серверных вызовов (например, тяжелых неделимых запросов к базе данных длительностью от 10 до 30 секунд) синхронное ожидание приводит к «зависанию» интерфейса клиентского приложения. Чтобы интерфейс оставался отзывчивым, такие действия выносят в фоновые задания. Однако возникает другая проблема: пользователь может забыть о запущенной операции, посчитать программу бездействующей и повторно нажать кнопку либо растеряться при внезапном обновлении формы.
Обычный прогресс-бар в подобных ситуациях не подходит, поскольку неделимый запрос к базе данных не отдает промежуточный прогресс выполнения в процентах. В таких сценариях наилучшим решением выступает спиннер (анимированный круговой индикатор загрузки). Разберем основные варианты реализации спиннера в 1С:Предприятие 8.3 как с использованием стандартных библиотек, так и полностью независимыми средствами.
Если в конфигурации внедрена «Библиотека Стандартных Подсистем» (БСП), разработчику доступен готовый программный интерфейс для запуска и отслеживания фоновых заданий. Подсистема автоматически показывает диалог ожидания со стандартной анимацией платформы и блокирует интерфейс от повторных нажатий.
Разберем по шагам типовой алгоритм работы через общий модуль ДлительныеОперацииКлиент:
ДлительныеОперацииКлиент.ОжидатьЗавершение(...), передавая параметры ожидания (текст сообщения, интервал проверки, форму-владелец).Посмотрим на пример клиентского кода запуска операции:
&НаКлиенте
Процедура ЗапуститьДлительнуюОперацию(Команда)
ПараметрыПроцедуры = Новый Структура("Организация, Период", Объект.Организация, Объект.Период);
ПараметрыВыполнения = ДлительныеОперацииКлиент.ПараметрыВыполненияФункции(ЭтотОбъект);
ПараметрыВыполнения.ТекстСообщения = "Выполняется расчет, пожалуйста, подождите...";
ДлительнаяОперация = ДлительныеОперацииКлиент.ЗапуститьФункцию(
"МойОбщийМодульСервер.ВыполнитьТяжелыйРасчет",
ПараметрыПроцедуры,
ПараметрыВыполнения
);
ОповещениеОЗавершении = Новый ОписаниеОповещения("ПослеЗавершенияОперации", ЭтотОбъект);
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
КонецПроцедуры
Когда БСП в конфигурации отсутствует, простейшим способом визуализации является размещение элемента формы типа Поле картинки, отображающего анимированный файл формата GIF.
Рассмотрим порядок настройки элементов:
Видимость = Ложь.Элементы.Спиннер.Видимость = Истина), а после завершения задания — скрываем его обратно.Анимированные GIF-файлы могут иметь артефакты масштабирования и проблемы с прозрачностью фона при смене темы оформления. Более гибкий и современный способ — элемент формы с видом Поле HTML документа.
Преимущества данного подхода:
Посмотрим, как инициализировать поле HTML документа кодом:
&НаСервере
Процедура ИнициализироватьСпиннер()
ТекстHTML =
"<html><head><style>
|body { margin: 0; background: transparent; display: flex; align-items: center; justify-content: center; height: 100vh; }
|.loader { border: 4px solid #f3f3f3; border-top: 4px solid #005fb8; border-radius: 50%; width: 32px; height: 32px; animation: spin 1s linear infinite; }
|@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|</style></head><body><div class=""loader""></div></body></html>";
HTMLКодСпиннера = ТекстHTML;
КонецПроцедуры
Вместо перегрузки текущей формы элементами спиннера создадим вспомогательную общую форму (например, «ФормаОжидания»), содержащую спиннер и надпись «Пожалуйста, подождите...».
Для предотвращения нежелательных действий пользователя открываем такую форму немодально с блокировкой владельца:
ПараметрыФормы = Новый Структура("ИдентификаторЗадания", ИдентификаторФоновогоЗадания);
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("РежимБлокировкиОкна", РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
ОткрытьФорму("ОбщаяФорма.ФормаОжидания", ПараметрыФормы, ЭтотОбъект, , , , , РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
Проанализируем полный цикл отслеживания состояния фонового задания штатным функционалом платформы 1С:
ФоновыеЗадания.Выполнить(...) запускает процедуру в отдельном потоке. Результат помещается во временное хранилище по уникальному адресу. Клиент получает УникальныйИдентификатор задания и адрес хранилища.Элементы.КнопкаВыполнить.Доступность = Ложь) и подключаем опрос через ПодключитьОбработчикОжидания("ПроверитьСостояниеЗадания", 1, Истина).ФоновыеЗадания.НайтиПоУникальномуИдентификатору(...):
Состояние равно СостояниеФоновогоЗадания.Активно — повторно подключаем обработчик ожидания.Состояние равно СостояниеФоновогоЗадания.Завершено — выключаем спиннер, восстанавливаем доступность элементов и забираем данные через ПолучитьИзВременногоХранилища(...).Состояние равно СостояниеФоновогоЗадания.ЗавершеноАварийно или СостояниеФоновогоЗадания.Отменено — отключаем анимацию и анализируем свойство ИнформацияОбОшибке для оповещения пользователя.Посмотрим на пример структуры серверной функции проверки состояния:
&НаСервереБезКонтекста
Функция ФоновоеЗаданиеЗавершено(ИдентификаторЗадания)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
Если Задание = Неопределено Тогда
ВызватьИсключение "Фоновое задание не найдено.";
КонецЕсли;
Если Задание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
Возврат Ложь;
ИначеЕсли Задание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
Возврат Истина;
Иначе
// При аварийном завершении или отмене
Если Задание.ИнформацияОбОшибке <> Неопределено Тогда
ВызватьИсключение ПодробноеПредставлениеОшибки(Задание.ИнформацияОбОшибке);
Иначе
ВызватьИсключение "Фоновое задание было отменено.";
КонецЕсли;
КонецЕсли;
КонецФункции
При реализации визуальных индикаторов необходимо учитывать следующие технические особенности платформы: