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