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