При разработке управляемого интерфейса в 1С разработчики нередко сталкиваются с ситуацией, когда форма документа, справочника или бизнес-процесса в тонком клиенте открывается мгновенно, а в веб-клиенте зависает на десятки секунд. Часто источником проблемы кажется безобидная строка установки видимости элемента формы, например: Элементы.ОплатыЗаказПоставщику.Видимость = Истина;. Разберем по шагам, почему так происходит, какие механизмы платформы запускаются при этом и как правильно устранить зависание интерфейса.
В отличие от тонкого клиента, где интерфейс отрисовывается нативным движком платформы, в веб-клиенте интерфейс строится в браузере с использованием структуры DOM и JavaScript. Программное переключение видимости колонок табличной части или динамических списков на сервере (в процедуре ПриСозданииНаСервере) либо на клиенте при открытии заставляет браузер полностью пересчитывать геометрию элементов страницы и позиционировать курсор.
В веб-клиенте эта перерисовка часто приводит к каскадному срабатыванию интерфейсных событий, в частности события ПриАктивизацииСтроки (вплоть до нескольких раз подряд при открытии одной формы). Если в этом обработчике написан тяжелый код, содержащий контекстные обращения к серверу (&НаСервере) или циклы, открытие формы блокируется на время выполнения всех сетевых запросов.
Проанализируем стандартные требования платформы к событию ПриАктивизацииСтроки. В синтакс-помощнике прямо указано, что в обработчике данного события крайне не рекомендуется выполнять синхронные вызовы процедур с директивой &НаСервере, так как они блокируют интерфейс при каждом перемещении фокуса и при обновлении геометрии таблицы.
Если получение данных с сервера действительно необходимо, используем директиву &НаСервереБезКонтекста, передавая только требуемый идентификатор или ссылку, чтобы исключить передачу всего контекста формы через HTTP-соединение:
&НаКлиенте
Процедура ОплатыПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Передаем только нужные реквизиты без контекста формы
ПолучитьДополнительныеДанныеНаСервере(ТекущиеДанные.ЗаказПоставщику);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПолучитьДополнительныеДанныеНаСервере(Знач ЗаказПоставщику)
// Оптимизированная выборка данных без сериализации формы
КонецПроцедуры
Чтобы исключить выполнение серверных процедур в момент, когда форма только загружается и веб-клиент перерисовывает колонки, введем переменную-флаг инициализации формы в модуле формы:
&НаКлиенте
Перем ФормаИнициализирована;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ФормаИнициализирована = Истина;
КонецПроцедуры
&НаКлиенте
Процедура ОплатыПриАктивизацииСтроки(Элемент)
// Прерываем выполнение, если форма еще находится на этапе отрисовки
Если Не ФормаИнициализирована Тогда
Возврат;
КонецЕсли;
ОбработатьВыборСтроки();
КонецПроцедуры
Веб-клиент может несколько раз активизировать одну и ту же строку при скрытии или отображении элементов. Чтобы не выполнять лишнюю работу, сохраняем идентификатор текущей строки в переменной модуля формы:
&НаКлиенте
Перем ИдентификаторПредыдущейСтроки;
&НаКлиенте
Процедура ОплатыПриАктивизацииСтроки(Элемент)
Если Элемент.ТекущаяСтрока = ИдентификаторПредыдущейСтроки Тогда
Возврат;
КонецЕсли;
ИдентификаторПредыдущейСтроки = Элемент.ТекущаяСтрока;
ОбработатьВыборСтроки();
КонецПроцедуры
Если по событию активации строки требуется выполнять относительно тяжелую операцию, самым надежным паттерном платформы 1С является отложенный вызов через ПодключитьОбработчикОжидания с однократным запуском. Это объединяет множество событий в одно и предотвращает «залипание» интерфейса:
&НаКлиенте
Процедура ОплатыПриАктивизацииСтроки(Элемент)
// Сбрасываем предыдущий вызов, если пользователь быстро листает строки
ОтключитьОбработчикОжидания("ВыполнитьОбработкуСтрокиПоОжиданию");
// Подключаем однократный вызов с минимальной задержкой в 0.1 секунды
ПодключитьОбработчикОжидания("ВыполнитьОбработкуСтрокиПоОжиданию", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьОбработкуСтрокиПоОжиданию()
// Здесь выполняются действия по обновлению данных формы
КонецПроцедуры
Для быстрого обнаружения неоптимального кода, специфичного для директивы #Если ВебКлиент Тогда, настроим отладку для веб-клиента. Для этого в файле публикации информационной базы default.vrd на веб-сервере включим режим отладки:
<debug enable="true" url="tcp://АдресСервераОтладки:1560"/>
После перезапуска веб-сервера подключимся конфигуратором к сеансу веб-клиента через меню Отладка — Подключение и определим стек вызовов, замедляющих открытие формы.