К статье
Практический материал

Разработка и Конфигурация · 11 мин

Вызов сервера в 1С: что это и как правильно его использовать

Что такое вызов сервера в 1С, как работают директивы &НаСервере и &НаКлиенте, как сократить число серверных вызовов и избежать типичных ошибок разработки.

Вызов сервера в 1С — это передача выполнения кода с клиентского приложения на сервер 1С:Предприятия. В управляемых формах платформа разделяет код на клиентский и серверный: интерфейс, обработка действий пользователя и работа с файлами выполняются на клиенте, а обращения к базе данных, запросы и объектная логика — на сервере. Каждый переход между этими контекстами и есть серверный вызов.

Такой вызов — не бесплатная операция. Он включает сериализацию данных, передачу по сети, выполнение кода в контексте сервера и возврат результата. В файловом режиме на локальном компьютере это почти незаметно, но в клиент-серверном варианте или при работе через веб-клиент и медленный канал каждый лишний вызов превращается в ощутимую задержку. Форма, которая при открытии делает десятки обращений к серверу, будет «подвисать» на несколько секунд.

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

Как устроено разделение кода в управляемой форме

В управляемой форме каждая процедура и функция помечается директивой компиляции, которая определяет, где будет исполняться код. Основные директивы: &НаКлиенте — код работает в клиентском приложении; &НаСервере — код выполняется на сервере с доступом к данным формы; &НаСервереБезКонтекста — серверный код без передачи данных формы; &НаКлиентеНаСервереБезКонтекста — код, доступный в обоих контекстах, но без доступа к реквизитам формы.

Когда клиентская процедура обращается к серверной, платформа выполняет полный цикл: упаковывает параметры и данные формы (если вызов контекстный), отправляет их на сервер, выполняет код, упаковывает результат и возвращает клиенту. Этот цикл и называется серверным вызовом. Важно, что один вызов может включать сколько угодно операций внутри серверной процедуры — запросы, чтение справочников, вычисления, — и всё это «стоит» как одно обращение.

Директивы &НаСервере и &НаСервереБезКонтекста: что выбрать

Ключевой практический выбор — между контекстным и бесконтекстным серверным вызовом. Контекстный вызов (&НаСервере) видит реквизиты формы и может их менять, но перетаскивает на сервер и обратно весь объём данных формы. Если в форме есть большая таблица значений или динамический список с тяжёлыми настройками, такой вызов заметно дороже.

Бесконтекстный вызов (&НаСервереБезКонтекста) получает только явно переданные параметры. Он быстрее и предпочтительнее, когда нужно, например, получить цену товара, остаток по складу или реквизиты контрагента по ссылке. Ограничение: такой метод не имеет доступа к данным формы напрямую — всё нужное передаётся параметрами, а результат возвращается клиенту, который сам обновляет элементы формы.

Сравнение вариантов

&НаСервере (контекстный)

Подходит, когда нужно изменить много реквизитов формы или пересчитать объект целиком. Ограничение: передаёт все данные формы, дорогой при больших таблицах.

&НаСервереБезКонтекста

Подходит для точечных операций: получить значение, проверить условие, выполнить запрос. Ограничение: нет доступа к реквизитам формы, данные передаются параметрами.

Общий серверный модуль

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

Как выполнить вызов сервера на практике

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

Пример реализации. В модуле формы создаются две процедуры: клиентский обработчик и серверная бесконтекстная функция, которая принимает ссылку на номенклатуру и возвращает цену.

&НаКлиенте

Процедура ТоварыНоменклатураПриИзменении(Элемент)

Строка = Элементы.Товары.ТекущиеДанные;

Строка.Цена = ПолучитьЦенуНаСервере(Строка.Номенклатура);

КонецПроцедуры

&НаСервереБезКонтекста

Функция ПолучитьЦенуНаСервере(Номенклатура)

Запрос = Новый Запрос(

"ВЫБРАТЬ Цена ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура = &Номенклатура)");

Запрос.УстановитьПараметр("Номенклатура", Номенклатура);

Выборка = Запрос.Выполнить().Выбрать();

Возврат ?(Выборка.Следующий(), Выборка.Цена, 0);

КонецФункции

Порядок действий
  1. 1
    Определите, какие данные нужны клиенту и можно ли получить их одним запросом
  2. 2
    Создайте серверную процедуру или функцию с директивой &НаСервереБезКонтекста, если доступ к реквизитам формы не нужен
  3. 3
    Передайте в неё только необходимые параметры — ссылки, даты, простые значения
  4. 4
    В клиентском обработчике вызовите серверную функцию и присвойте результат нужным полям
  5. 5
    Проверьте форму в тонком и веб-клиенте: результат должен быть одинаковым, без ошибок о недоступных операциях

Если нужно изменить сразу несколько реквизитов объекта или пересчитать табличную часть целиком, разумнее сделать один контекстный вызов &НаСервере, который выполнит все действия за одно обращение, чем серию бесконтекстных вызовов по каждому полю.

Почему лишние вызовы сервера замедляют работу

Каждый серверный вызов несёт постоянные накладные расходы: установка соединения, сериализация и десериализация данных, переключение контекста. На быстрой локальной сети это миллисекунды, но при работе через интернет, VPN или веб-клиент задержка на один вызов может достигать сотен миллисекунд. Десять последовательных вызовов в обработчике — уже заметная пауза для пользователя.

Классическая ошибка — вызов сервера в цикле. Например, при загрузке табеля разработчик для каждой строки вызывает серверную функцию получения данных сотрудника. При 200 строках это 200 обращений к серверу. Правильное решение — собрать все ссылки в массив или таблицу значений, передать их одним параметром и выполнить один запрос с условием В (&СписокСсылок).

Типичные ошибки
01
Вызов сервера внутри цикла по строкам таблицы — вместо одного запроса с пакетом данных форма делает десятки обращений и заметно тормозит
02
Контекстный вызов &НаСервере ради чтения одного значения — на сервер передаются все данные формы, включая большие таблицы
03
Попытка выполнить на клиенте операции, доступные только на сервере (запросы, работа с объектами через менеджеры) — код падает с ошибкой компиляции или выполнения
04
Возврат из серверной функции сложных объектов (ДокументОбъект, СправочникОбъект) — такие объекты не сериализуются для клиента, возвращать нужно ссылки или структуры
05
Игнорирование кэширования: одни и те же данные (например, настройки пользователя) запрашиваются при каждом событии вместо однократного получения

Как сократить количество серверных вызовов

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

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

Третий приём — использование асинхронных механизмов там, где результат не нужен немедленно: фоновые задания и длительные операции позволяют не блокировать интерфейс, пока сервер выполняет тяжёлую обработку. Для длительных расчётов это предпочтительнее синхронного вызова, во время которого форма «замораживается».

Как диагностировать проблемы с вызовами сервера

Основной инструмент — замер производительности в конфигураторе (Отладка → Замер производительности). Он показывает, какие процедуры сколько времени заняли и сколько раз вызывались. Если при одном действии пользователя серверная функция срабатывает сотни раз, источник проблемы найден.

Дополнительно помогает технологический журнал с включёнными событиями CALL и SCALL: он фиксирует обращения между клиентом и сервером с длительностью каждого. По этим данным можно отличить «много дешёвых вызовов» от «одного тяжёлого запроса» — стратегии оптимизации в этих случаях разные.

Контрольные точки

Как проверить результат

Число серверных вызовов при типовом действии пользователя
Норма

Одно-два обращения на действие, остальное выполняется на клиенте или пакетно

Тревожный признак

Десятки вызовов за одно действие, особенно внутри циклов

Время отклика формы в тонком/веб-клиенте
Норма

Реакция на изменение поля — менее секунды без видимых пауз

Тревожный признак

Заметные подвисания при каждом изменении данных

Тип серверных процедур в модуле формы
Норма

Точечные операции вынесены в &НаСервереБезКонтекста, контекстные вызовы — только для массовых изменений формы

Тревожный признак

Все серверные методы контекстные, включая чтение одиночных значений

Ограничения и границы безопасной работы

На клиенте недоступны: запросы, прямая работа с объектами базы данных (ДокументОбъект, СправочникОбъект), менеджеры прикладных объектов, транзакции. Всё это требует серверного контекста. Обратно: на сервере недоступны интерактивные операции — вопросы пользователю, предупреждения, открытие форм, работа с файловой системой клиента.

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

FAQ: частые вопросы о вызове сервера в 1С

Почему возникает ошибка «Вызов сервера запрещен»?

Чаще всего причина в настройках общего модуля: у него снят флаг «Вызов сервера», либо включён флаг «Клиент (обычное приложение)» без «Сервер». Откройте свойства модуля в конфигураторе и проверьте, что установлены флаги «Сервер» и «Вызов сервера». Также ошибка возможна при вызове серверной процедуры из контекста, где серверные вызовы недоступны по настройкам безопасности.

Чем &НаСервереБезКонтекста лучше &НаСервере?

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

Можно ли вызвать серверную процедуру из обычной формы?

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

Как понять, что форма делает слишком много вызовов сервера?

Признаки: форма долго открывается, поля реагируют с задержкой, интерфейс «подвисает» при изменении данных. Подтвердить можно замером производительности в конфигураторе или анализом технологического журнала по событиям CALL — там видно количество и длительность обращений за одно действие пользователя.

Можно ли передать таблицу значений с клиента на сервер?

Да, таблица значений сериализуется и может передаваться параметром в серверную процедуру. Но учитывайте объём: таблица на десятки тысяч строк сделает вызов тяжёлым. В таких случаях лучше передать отбор или параметры и построить данные запросом уже на сервере.

Итог

Что важно запомнить

Вызов сервера — это обращение клиентского кода управляемой формы к серверным процедурам, и каждый такой вызов стоит времени на передачу данных. Используйте &НаСервереБезКонтекста для точечных операций, группируйте действия в один вызов, никогда не вызывайте сервер в цикле и проверяйте результат замером производительности в тонком или веб-клиенте.