При разработке мониторингов, рабочих столов или дашбордов в 1С часто возникает задача обеспечения актуальности данных в реальном времени. Если информация в базе данных меняется ежесекундно (например, приход товаров или оплаты), пользователю неудобно каждый раз нажимать кнопку «Обновить». В этой статье мы подробно разберем, как автоматизировать этот процесс, минимизировать нагрузку на сервер и решить проблему «забытого фокуса» окна.
Самый прямолинейный и популярный способ обновления данных — использование встроенного метода ПодключитьОбработчикОжидания. Этот механизм позволяет платформе периодически вызывать заданную процедуру на клиенте.
Рассмотрим по шагам, как это реализовать. В модуле управляемой формы нам необходимо инициировать процесс при открытии формы:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Обновляем данные каждые 10 секунд
ПодключитьОбработчикОжидания("ОбновитьДанныеМонитора", 10);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДанныеМонитора()
// Здесь вызывается серверная процедура получения данных
ОбновитьДанныеНаСервере();
КонецПроцедуры
Важно помнить, что если форма закрывается, обработчик прекращает свою работу автоматически. Однако, если логика требует остановки обновления в процессе работы, используйте метод ОтключитьОбработчикОжидания("ИмяПроцедуры"). Основной риск здесь — нагрузка на сервер, если 30 и более пользователей будут одновременно запрашивать «тяжелые» данные.
Чтобы сервер не «загнулся» от постоянных запросов, проанализируем ситуацию. Вместо того чтобы каждые несколько секунд пересчитывать все итоги, мы можем сначала спросить у сервера: «А изменилось ли что-то вообще?». Для этого лучше всего использовать внеконтекстные серверные вызовы.
Разберем пример оптимизированного обновления. Мы будем проверять некую «версию данных» или время последнего изменения в специальном регистре сведений.
&НаКлиенте
Процедура ОбновитьДанныеМонитора()
// Передаем текущую версию данных, которая хранится в реквизите формы
Если ПроверитьНаличиеИзмененийНаСервере(ПоследняяВерсияДанных) Тогда
ОбновитьДанныеНаСервере();
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьНаличиеИзмененийНаСервере(ТекущаяВерсия)
// Максимально быстрый запрос к базе данных
АктуальнаяВерсия = Константы.ВерсияДанныхМониторинга.Получить();
Возврат АктуальнаяВерсия <> ТекущаяВерсия;
КонецФункции
Использование директивы &НаСервереБезКонтекста критически важно, так как при таком вызове на сервер не передаются все данные формы (реквизиты, таблицы), что значительно экономит трафик и ресурсы процессора.
Если изменения инициируются тем же пользователем в соседнем окне (например, он открыл документ из монитора, провел его и вернулся), можно использовать механизм оповещений. Рассмотрим, как связать форму монитора и форму документа.
В форме документа, который вносит изменения, в процедуре после записи пишем:
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
Оповестить("ДанныеМонитораИзменены", , ЭтаФорма);
КонецПроцедуры
А в форме монитора реализуем обработку этого события:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ДанныеМонитораИзменены" Тогда
ОбновитьДанныеНаСервере();
КонецЕсли;
КонецПроцедуры
Важное ограничение: этот метод работает только в рамках одного клиентского сеанса. Если документ проведет один пользователь, у другого пользователя в мониторе это событие не сработает автоматически.
Если ваш монитор представляет собой таблицу со списком документов или записей регистра, проанализируем возможности объекта ДинамическийСписок. У него есть штатное свойство ПериодАвтообновления.
Платформа сама будет опрашивать базу данных. Однако стоит учитывать, что для сложных запросов с объединениями таблиц (UNION) автоматическое обновление может работать некорректно или создавать избыточную нагрузку. Для решения нестандартных задач отображения данных можно изучить практические методы доработки динамических списков.
Выясним причину, по которой стандартное событие ПриПовторномОткрытии часто не срабатывает. Оно возникает только при вызове метода ОткрытьФорму для уже открытого окна, но не при простом переключении между окнами мышкой.
Красивого штатного решения для события «При получении фокуса» в 1С 8.2/8.3 нет. Но мы можем применить «костыль» с использованием Обработчика ожидания, который проверяет активность. Либо, что более эффективно, использовать событие ПриАктивизацииСтроки или ПриАктивизацииЭлемента. Как только пользователь кликнет в любое место формы после возвращения к ней, сработает код обновления.
Если вы работаете на современных версиях платформы, рассмотрим самый прогрессивный метод — Систему взаимодействия. Она позволяет серверу самому «толкать» (Push) уведомление клиенту.
При проведении документа на сервере программно отправляется сообщение в специальный канал. Форма монитора «подписывается» на этот канал. Как только сообщение приходит, на клиенте мгновенно срабатывает обработчик оповещения. Это полностью снимает проблему холостых запросов к серверу, так как обновление происходит только в момент реального изменения данных.
Для создания надежного мониторинга мы рекомендуем придерживаться следующей стратегии:
ПодключитьОбработчикОжидания с разумным интервалом (от 15-30 секунд и выше).&НаСервереБезКонтекста функцию для быстрой проверки изменений.Таким образом, мы обеспечим баланс между актуальностью данных и производительностью серверной части системы. Для неблокирующего выполнения тяжелых операций обновления без привязки к БСП можно использовать пример организации фоновых заданий с отслеживанием результата.