Как в ПослеЗаписиНаСервере понять, что форма будет закрыта (нажато «Провести и закрыть»)?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки управляемых форм в «1С:Предприятии 8.3» программисты часто сталкиваются с задачами оптимизации интерфейса. Типичный сценарий: после записи или проведения документа на форме необходимо обновить сопутствующие данные, перечитать связанные регистры, изменить видимость или доступность кнопок. Все эти операции выполняются на сервере в обработчике ПослеЗаписиНаСервере и могут занимать значительное время (от нескольких десятых долей секунды до нескольких секунд).

Однако если пользователь нажал кнопку «Записать и закрыть» или «Провести и закрыть», форма мгновенно прекратит свое существование на клиенте сразу после завершения транзакции записи. В этом случае тратить драгоценные серверные ресурсы и время пользователя на пересчет и перечитывание данных управляемой формы абсолютно бессмысленно. Возникает закономерный вопрос: как в событии ПослеЗаписиНаСервере определить, закроется ли форма сразу после записи?

В этой статье мы подробно разберем особенности жизненного цикла формы, выясним, почему платформа по умолчанию не предоставляет такого флага, и рассмотрим четыре практических способа решения этой проблемы.

Почему платформа не передает этот флаг по умолчанию?

Давайте проанализируем последовательность выполнения событий при записи объекта в управляемом интерфейсе 1С. Когда пользователь нажимает кнопку «Провести и закрыть», платформа запускает стандартный сценарий:

  1. Вызывается клиентский обработчик ПередЗаписью.
  2. Вызываются серверные обработчики транзакции записи (ПередЗаписьюНаСервере, ПриЗаписиНаСервере, запись в базу данных, ПослеЗаписиНаСервере).
  3. Вызывается клиентский обработчик ПослеЗаписи.
  4. Инициируется закрытие формы: вызываются обработчики ПередЗакрытием и ПриЗакрытии на клиенте.

Платформа разделяет процесс записи данных и процесс управления интерфейсом. На уровне сервера запись — это изолированная транзакционная операция над базой данных. Сервер не «знает» и не должен знать, что планирует делать клиентское приложение с формой после того, как запись завершится. Именно поэтому в стандартной структуре ПараметрыЗаписи на сервере доступны только базовые свойства, такие как РежимЗаписи и РежимПроведения.

Тем не менее, решить эту задачу можно с помощью нескольких архитектурных обходов.

Способ 1. Использование собственных команд и параметров записи

Самый надежный и прозрачный способ связать намерение пользователя закрыть форму с серверными процедурами — передача специального флага через структуру ПараметрыЗаписи. Эта структура передается сквозь всю цепочку событий записи и доступна как на клиенте, так и на сервере.

Для реализации этого подхода выполним следующие шаги:

  1. Скроем стандартные командные кнопки «Записать и закрыть» или «Провести и закрыть» на форме документа.
  2. Создадим собственную команду формы, например, ЗаписатьИЗакрытьСобственная, и разместим ее на командной панели.
  3. В обработчике этой команды на клиенте сформируем структуру параметров записи и принудительно вызовем запись формы.

Рассмотрим пример кода на клиенте:


&НаКлиенте
Процедура ЗаписатьИЗакрытьСобственная(Команда)
    
    ПараметрыЗаписи = Новый Структура;
    // Добавляем собственный флаг закрытия формы
    ПараметрыЗаписи.Вставить("ЗакрытьПослеЗаписи", Истина);
    
    // Если работаем с документом, указываем стандартные режимы
    ПараметрыЗаписи.Вставить("РежимЗаписи", РежимЗаписиДокумента.Проведение);
    
    // Запускаем штатный процесс записи формы с нашими параметрами
    Записать(ПараметрыЗаписи);
    
КонецПроцедуры

Теперь наш флаг ЗакрытьПослеЗаписи будет доступен в серверном обработчике. Проанализируем, как обработать его на сервере:


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    
    ЗакрыватьФорму = Ложь;
    Если ПараметрыЗаписи.Свойство("ЗакрытьПослеЗаписи", ЗакрыватьФорму) И ЗакрыватьФорму Тогда
        // Форма будет закрыта на клиенте, прерываем выполнение тяжелых алгоритмов
        Возврат;
    КонецЕсли;
    
    // Логика обновления интерфейса и чтения смежных данных, если форма остается открытой
    ОбновитьСмежныеДанныеФормы(ТекущийОбъект);
    
КонецПроцедуры

После завершения серверных процедур управление возвращается на клиент. Нам необходимо физически закрыть форму, если запись прошла успешно:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    
    ЗакрыватьФорму = Ложь;
    Если ПараметрыЗаписи.Свойство("ЗакрытьПослеЗаписи", ЗакрыватьФорму) И ЗакрыватьФорму Тогда
        Закрыть();
    КонецЕсли;
    
КонецПроцедуры

Способ 2. Использование штатных механизмов БСП (Библиотеки Стандартных Подсистем)

Если вы ведете разработку в современной типовой конфигурации 1С (например, УТ 11, ERP, КА, БП 3.0), то в ней практически наверняка используется БСП. Разработчики БСП уже стандартизировали этот сценарий.

При нажатии стандартных кнопок записи и закрытия в БСП-конфигурациях вызываются общие модули клиентского уровня (например, ОбщегоНазначенияУТКлиент). В процедуре подготовки записи система автоматически формирует параметр ЗакрытьПослеЗаписи (или ПринудительноЗакрытьФорму) внутри структуры ПараметрыЗаписи.

Прежде чем создавать собственные кнопки, выполните простой эксперимент: поставьте точку останова в процедуре ПослеЗаписиНаСервере вашей формы и нажмите стандартную кнопку «Провести и закрыть». Проверьте содержимое переменной ПараметрыЗаписи в табло отладки. Во многих современных конфигурациях вы обнаружите там готовый флаг, который можно использовать напрямую:


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    
    // Пример для конфигураций на базе БСП
    ЗакрытьПослеЗаписи = Ложь;
    Если ПараметрыЗаписи.Свойство("ЗакрытьПослеЗаписи", ЗакрытьПослеЗаписи) И ЗакрытьПослеЗаписи Тогда
        Возврат; 
    КонецЕсли;
    
    // Основной код обновления...
    
КонецПроцедуры

Способ 3. Отложенное обновление через обработчик ожидания (Архитектурный обход)

Если вам крайне нежелательно скрывать стандартные кнопки платформы, переопределять команды и вмешиваться в штатную логику записи БСП, существует изящный архитектурный обходной путь. Мы можем перенести тяжелую операцию чтения данных с серверного события записи на отложенное клиентское событие.

Суть метода заключается в использовании однократного обработчика ожидания с минимальным интервалом времени (например, 0.1 секунды).

Разберем этот алгоритм по шагам:

  1. В обработчике ПослеЗаписиНаСервере мы вообще не выполняем никакого тяжелого чтения данных.
  2. В клиентском обработчике ПослеЗаписи мы подключаем обработчик ожидания.
  3. Если пользователь нажал «Записать и закрыть», платформа сразу после выполнения ПослеЗаписи начинает уничтожение контекста формы и закрывает ее. Подключенный обработчик ожидания просто уничтожается вместе с формой и никогда не выполняется. Сервер не нагружается лишней работой.
  4. Если пользователь нажал обычную кнопку «Записать», форма остается открытой. Спустя 0.1 секунды срабатывает наш обработчик ожидания на клиенте, который вызывает серверную процедуру для обновления данных формы.

Посмотрим на программную реализацию этого метода:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    
    // Подключаем однократный обработчик ожидания на 0.1 секунды
    ПодключитьОбработчикОжидания("ВыполнитьОтложенноеОбновлениеДанных", 0.1, Истина);
    
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьОтложенноеОбновлениеДанных()
    
    // Этот код сработает, только если форма осталась открыта
    ОбновитьДанныеНаСервере();
    
КонецПроцедуры

&НаСервере
Процедура ОбновитьДанныеНаСервере()
    
    // Выполняем тяжелые запросы и обновляем реквизиты формы
    ПрочитатьСмежныеРегистрыИОбновитьИнтерфейс();
    
КонецПроцедуры

Этот способ является наиболее универсальным, так как он не требует модификации интерфейса командной панели формы и работает стабильно на любой версии платформы «1С:Предприятие 8».

Резюме и рекомендации

Мы рассмотрели различные варианты решения проблемы. Выбор конкретного метода зависит от архитектуры вашего решения:

← На главную