Разработка и Конфигурация · 11 мин
Вызов сервера в 1С: что это и как правильно его использовать
Что такое вызов сервера в 1С, как работают директивы &НаСервере и &НаКлиенте, как сократить число серверных вызовов и избежать типичных ошибок разработки.
Вызов сервера в 1С — это передача выполнения кода с клиентского приложения на сервер 1С:Предприятия. В управляемых формах платформа разделяет код на клиентский и серверный: интерфейс, обработка действий пользователя и работа с файлами выполняются на клиенте, а обращения к базе данных, запросы и объектная логика — на сервере. Каждый переход между этими контекстами и есть серверный вызов.
Такой вызов — не бесплатная операция. Он включает сериализацию данных, передачу по сети, выполнение кода в контексте сервера и возврат результата. В файловом режиме на локальном компьютере это почти незаметно, но в клиент-серверном варианте или при работе через веб-клиент и медленный канал каждый лишний вызов превращается в ощутимую задержку. Форма, которая при открытии делает десятки обращений к серверу, будет «подвисать» на несколько секунд.
Понимание механизма серверных вызовов нужно и разработчику, и администратору: разработчик проектирует формы так, чтобы минимизировать обмен данными, а администратор по симптомам медленной работы может отличить проблему в коде от проблемы в инфраструктуре. Ниже разобраны директивы компиляции, режимы вызова, способы сократить количество обращений и типичные ошибки.
Как устроено разделение кода в управляемой форме
В управляемой форме каждая процедура и функция помечается директивой компиляции, которая определяет, где будет исполняться код. Основные директивы: &НаКлиенте — код работает в клиентском приложении; &НаСервере — код выполняется на сервере с доступом к данным формы; &НаСервереБезКонтекста — серверный код без передачи данных формы; &НаКлиентеНаСервереБезКонтекста — код, доступный в обоих контекстах, но без доступа к реквизитам формы.
Когда клиентская процедура обращается к серверной, платформа выполняет полный цикл: упаковывает параметры и данные формы (если вызов контекстный), отправляет их на сервер, выполняет код, упаковывает результат и возвращает клиенту. Этот цикл и называется серверным вызовом. Важно, что один вызов может включать сколько угодно операций внутри серверной процедуры — запросы, чтение справочников, вычисления, — и всё это «стоит» как одно обращение.
Директивы &НаСервере и &НаСервереБезКонтекста: что выбрать
Ключевой практический выбор — между контекстным и бесконтекстным серверным вызовом. Контекстный вызов (&НаСервере) видит реквизиты формы и может их менять, но перетаскивает на сервер и обратно весь объём данных формы. Если в форме есть большая таблица значений или динамический список с тяжёлыми настройками, такой вызов заметно дороже.
Бесконтекстный вызов (&НаСервереБезКонтекста) получает только явно переданные параметры. Он быстрее и предпочтительнее, когда нужно, например, получить цену товара, остаток по складу или реквизиты контрагента по ссылке. Ограничение: такой метод не имеет доступа к данным формы напрямую — всё нужное передаётся параметрами, а результат возвращается клиенту, который сам обновляет элементы формы.
Сравнение вариантов
Подходит, когда нужно изменить много реквизитов формы или пересчитать объект целиком. Ограничение: передаёт все данные формы, дорогой при больших таблицах.
Подходит для точечных операций: получить значение, проверить условие, выполнить запрос. Ограничение: нет доступа к реквизитам формы, данные передаются параметрами.
Подходит для переиспользуемой логики, вызываемой из разных форм. Ограничение: у модуля должны быть включены флаги «Сервер» и при необходимости «Вызов сервера».
Как выполнить вызов сервера на практике
Типовой сценарий: пользователь выбирает товар в строке документа, и нужно подставить цену из регистра сведений. Запрос к регистру возможен только на сервере, поэтому клиентский обработчик события ПриИзменении вызывает серверную функцию.
Пример реализации. В модуле формы создаются две процедуры: клиентский обработчик и серверная бесконтекстная функция, которая принимает ссылку на номенклатуру и возвращает цену.
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
Строка = Элементы.Товары.ТекущиеДанные;
Строка.Цена = ПолучитьЦенуНаСервере(Строка.Номенклатура);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЦенуНаСервере(Номенклатура)
Запрос = Новый Запрос(
"ВЫБРАТЬ Цена ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура = &Номенклатура)");
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Возврат ?(Выборка.Следующий(), Выборка.Цена, 0);
КонецФункции
- 1Определите, какие данные нужны клиенту и можно ли получить их одним запросом
- 2Создайте серверную процедуру или функцию с директивой &НаСервереБезКонтекста, если доступ к реквизитам формы не нужен
- 3Передайте в неё только необходимые параметры — ссылки, даты, простые значения
- 4В клиентском обработчике вызовите серверную функцию и присвойте результат нужным полям
- 5Проверьте форму в тонком и веб-клиенте: результат должен быть одинаковым, без ошибок о недоступных операциях
Если нужно изменить сразу несколько реквизитов объекта или пересчитать табличную часть целиком, разумнее сделать один контекстный вызов &НаСервере, который выполнит все действия за одно обращение, чем серию бесконтекстных вызовов по каждому полю.
Почему лишние вызовы сервера замедляют работу
Каждый серверный вызов несёт постоянные накладные расходы: установка соединения, сериализация и десериализация данных, переключение контекста. На быстрой локальной сети это миллисекунды, но при работе через интернет, VPN или веб-клиент задержка на один вызов может достигать сотен миллисекунд. Десять последовательных вызовов в обработчике — уже заметная пауза для пользователя.
Классическая ошибка — вызов сервера в цикле. Например, при загрузке табеля разработчик для каждой строки вызывает серверную функцию получения данных сотрудника. При 200 строках это 200 обращений к серверу. Правильное решение — собрать все ссылки в массив или таблицу значений, передать их одним параметром и выполнить один запрос с условием В (&СписокСсылок).
Как сократить количество серверных вызовов
Первый приём — группировка. Если при открытии формы нужно получить несколько независимых значений (валюту, текущего пользователя, настройки), их следует собрать в одну серверную функцию, возвращающую структуру, а не вызывать отдельный метод для каждого значения.
Второй приём — перенос логики в общие серверные модули с флагом «Вызов сервера». Такой модуль позволяет вызывать серверные функции из клиентского кода напрямую, без создания обёрток в модуле формы. Дополнительно модуль может кэшировать данные на время сеанса, если включён режим повторного использования возвращаемых значений.
Третий приём — использование асинхронных механизмов там, где результат не нужен немедленно: фоновые задания и длительные операции позволяют не блокировать интерфейс, пока сервер выполняет тяжёлую обработку. Для длительных расчётов это предпочтительнее синхронного вызова, во время которого форма «замораживается».
Как диагностировать проблемы с вызовами сервера
Основной инструмент — замер производительности в конфигураторе (Отладка → Замер производительности). Он показывает, какие процедуры сколько времени заняли и сколько раз вызывались. Если при одном действии пользователя серверная функция срабатывает сотни раз, источник проблемы найден.
Дополнительно помогает технологический журнал с включёнными событиями CALL и SCALL: он фиксирует обращения между клиентом и сервером с длительностью каждого. По этим данным можно отличить «много дешёвых вызовов» от «одного тяжёлого запроса» — стратегии оптимизации в этих случаях разные.
Как проверить результат
Одно-два обращения на действие, остальное выполняется на клиенте или пакетно
Десятки вызовов за одно действие, особенно внутри циклов
Реакция на изменение поля — менее секунды без видимых пауз
Заметные подвисания при каждом изменении данных
Точечные операции вынесены в &НаСервереБезКонтекста, контекстные вызовы — только для массовых изменений формы
Все серверные методы контекстные, включая чтение одиночных значений
Ограничения и границы безопасной работы
На клиенте недоступны: запросы, прямая работа с объектами базы данных (ДокументОбъект, СправочникОбъект), менеджеры прикладных объектов, транзакции. Всё это требует серверного контекста. Обратно: на сервере недоступны интерактивные операции — вопросы пользователю, предупреждения, открытие форм, работа с файловой системой клиента.
При передаче данных между контекстами действует ограничение на сериализуемость: между клиентом и сервером можно передавать примитивные типы, ссылки, структуры, массивы, таблицы значений, но нельзя передавать объекты базы данных, запросы, построители отчётов. Попытка вернуть такой объект из серверной функции приведёт к ошибке.
FAQ: частые вопросы о вызове сервера в 1С
Почему возникает ошибка «Вызов сервера запрещен»?
Чаще всего причина в настройках общего модуля: у него снят флаг «Вызов сервера», либо включён флаг «Клиент (обычное приложение)» без «Сервер». Откройте свойства модуля в конфигураторе и проверьте, что установлены флаги «Сервер» и «Вызов сервера». Также ошибка возможна при вызове серверной процедуры из контекста, где серверные вызовы недоступны по настройкам безопасности.
Чем &НаСервереБезКонтекста лучше &НаСервере?
Бесконтекстный вызов не передаёт на сервер данные формы, поэтому выполняется быстрее, особенно в формах с большими таблицами. Его недостаток — нет доступа к реквизитам формы: всё нужное передаётся параметрами, а изменения клиент применяет сам после получения результата.
Можно ли вызвать серверную процедуру из обычной формы?
В обычных формах нет жёсткого разделения клиентского и серверного контекста, как в управляемых: весь модуль исполняется в одном контексте, и директивы компиляции не используются. Механизм явных серверных вызовов — особенность именно управляемых форм и клиент-серверной архитектуры управляемого приложения.
Как понять, что форма делает слишком много вызовов сервера?
Признаки: форма долго открывается, поля реагируют с задержкой, интерфейс «подвисает» при изменении данных. Подтвердить можно замером производительности в конфигураторе или анализом технологического журнала по событиям CALL — там видно количество и длительность обращений за одно действие пользователя.
Можно ли передать таблицу значений с клиента на сервер?
Да, таблица значений сериализуется и может передаваться параметром в серверную процедуру. Но учитывайте объём: таблица на десятки тысяч строк сделает вызов тяжёлым. В таких случаях лучше передать отбор или параметры и построить данные запросом уже на сервере.
Что важно запомнить
Вызов сервера — это обращение клиентского кода управляемой формы к серверным процедурам, и каждый такой вызов стоит времени на передачу данных. Используйте &НаСервереБезКонтекста для точечных операций, группируйте действия в один вызов, никогда не вызывайте сервер в цикле и проверяйте результат замером производительности в тонком или веб-клиенте.