При изучении типовых конфигураций 1С на управляемых формах часто можно встретить конструкцию вида ПодключитьОбработчикОжидания("СписокПриАктивизацииСтрокиОбработчикОжидания", 0.1, Истина) внутри события таблицы ПриАктивизацииСтроки. На первый взгляд такой подход кажется избыточным усложнением, ведь логику обновления связанных данных можно написать непосредственно в обработчике события. Однако прямое выполнение тяжелых операций или контекстных серверных вызовов в этом событии приводит к серьезным проблемам с производительностью и стабильностью интерфейса. Рассмотрим подробно, почему разработчики платформы и типовых решений используют именно такой паттерн и как правильно его реализовывать.
Проанализируем поведение пользователя при работе со списком. Когда пользователь зажимает клавишу стрелки «Вверх» или «Вниз» на клавиатуре либо быстро прокручивает список колесиком мыши, фокус проходит через десятки строк за секунду. Если в обработчике ПриАктивизацииСтроки прописан прямой вызов сервера (например, расчет остатков, получение цен, картинок или истории взаиморасчетов), платформа попытается выполнить этот код для каждой промежуточной строки.
В результате интерфейс зависает, отклик на действия пользователя замедляется, а сервер нагружается бесполезными запросами. Использование однократного обработчика ожидания с интервалом 0.1 секунды решает эту проблему:
Выясним архитектурные ограничения платформы 1С:Предприятие 8.3. В событии таблицы ПриАктивизацииСтроки действует жесткое ограничение на вызов процедур с директивой &НаСервере (с передачей контекста формы).
Если из события вызвать серверную процедуру, которая изменяет состояние формы (например, состав элементов, видимость или доступность), сервер возвращает клиенту обновленное описание формы. Это приводит к повторной перерисовке таблицы и повторному вызову события ПриАктивизацииСтроки, формируя бесконечную рекурсию и аварийное завершение работы сеанса. Отложенный вызов через ПодключитьОбработчикОжидания разрывает стек событий интерфейса и исполняется независимо, что делает работу с формой безопасной.
Разберем по шагам, как корректно внедрить данный паттерн в модуль управляемой формы. Для надежной работы необходимо не только подключить таймер, но и отсечь паразитные срабатывания при повторном получении фокуса, а также проверить доступность данных.
Объявим клиентскую переменную для хранения идентификатора ранее обработанной строки и настроим события формы:
&НаКлиенте
Перем ПредыдущаяАктивизированнаяСтрока;
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
// Проверяем, изменилась ли строка фактически
ТекущаяСтрока = Элемент.ТекущаяСтрока;
Если ТекущаяСтрока = ПредыдущаяАктивизированнаяСтрока Тогда
Возврат;
КонецЕсли;
ПредыдущаяАктивизированнаяСтрока = ТекущаяСтрока;
// Подключаем однократный обработчик с задержкой 0.1 секунды
ПодключитьОбработчикОжидания("СписокПриАктивизацииСтрокиОбработчикОжидания", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура СписокПриАктивизацииСтрокиОбработчикОжидания()
// Проверяем наличие выделенной строки на момент срабатывания таймера
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Вызываем внеконтекстную процедуру сервера для получения данных
ОбновитьСвязанныеДанныеНаСервере(ТекущиеДанные.Ссылка);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОбновитьСвязанныеДанныеНаСервере(СсылкаНаОбъект)
// Выполняем выборку остатков, цен или сопутствующей информации
КонецПроцедуры
При использовании обработчиков ожидания обратим внимание на следующие правила:
Неопределено: К моменту срабатывания таймера (через 0.1 сек) пользователь может закрыть форму, изменить отбор или удалить строку. Обязательно проверяйте свойство ТекущиеДанные перед обращением к колонкам.&НаСервереБезКонтекста: Для минимизации объема сетевого трафика между клиентом и сервером передавайте в серверный метод только ключевые параметры (ссылку на объект, дату или ключ строки), избегая полной передачи состояния формы.ПодключитьОбработчикОжидания обязательно должен иметь значение Истина, иначе процедура продолжит циклически выполняться каждые 100 миллисекунд.Рассмотрим варианты, когда можно полностью обойтись без обработчиков ожидания и дополнительных вызовов сервера:
Элементы.Список.ТекущиеДанные.Поле.