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

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

НаСервереБезКонтекста в 1С 8.3: что это значит и как применять

Что означает директива НаСервереБезКонтекста в 1С 8.3, чем отличается от НаСервере, когда применять, ограничения и типичные ошибки разработчиков.

Директива &НаСервереБезКонтекста в 1С 8.3 указывает, что процедура или функция модуля формы выполняется на сервере, но при этом ей недоступен контекст формы — её реквизиты, элементы и данные объекта. Это одна из четырёх директив компиляции модуля формы наряду с &НаКлиенте, &НаСервере и &НаКлиентеНаСервереБезКонтекста.

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

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

Что означает директива НаСервереБезКонтекста

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

Пример объявления:

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

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

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

Запрос.Текст = "ВЫБРАТЬ Цена ИЗ РегистрСведений.ЦеныТоваров

|ГДЕ Товар = &Товар";

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

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

Если Выборка.Следующий() Тогда

Возврат Выборка.Цена;

КонецЕсли;

Возврат 0;

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

Функция получает ссылку на товар параметром и возвращает цену. Контекст формы ей не нужен — значит, платформа не тратит время на его подготовку и передачу.

Чем отличаются директивы компиляции модуля формы

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

ДирективаГде выполняетсяДоступ к контексту формыТипичное применение
&НаКлиентеНа клиентеДаРеакция на действия пользователя, работа с файлами, диалоги
&НаСервереНа сервереДа (контекст передаётся)Изменение реквизитов формы, программное создание элементов
&НаСервереБезКонтекстаНа сервереНетЗапросы к БД, чтение справочников, расчёты без привязки к форме
&НаКлиентеНаСервереБезКонтекстаИ там, и тамНетВспомогательные вычисления без обращения к БД

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

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

НаСервере

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

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

Подходит для чтения данных из БД по параметрам. Ограничение: нельзя обратиться к реквизитам и элементам формы.

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

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

Когда использовать НаСервереБезКонтекста

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

  • получение цены, остатка, характеристики по выбранному товару;
  • проверка существования элемента справочника по наименованию или коду;
  • чтение констант и настроек, хранящихся в базе;
  • выполнение запроса для заполнения списка выбора;
  • поиск связанных документов по ссылке.

Менее очевидный, но важный случай — работа с реквизитами объектов по ссылке. В тонком клиенте нельзя «разыменовать» ссылку через точку (Товар.Наименование вызовет ошибку), потому что объект находится на сервере. Стандартное решение — серверная функция без контекста, которая принимает ссылку и возвращает нужные поля.

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

Ограничения и подводные камни

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

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

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

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

Как проверить, что директива выбрана правильно

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

Практический тест: попробуйте сменить директиву с &НаСервере на &НаСервереБезКонтекста и выполнить проверку модуля в конфигураторе. Если ошибок нет — контекст процедуре не был нужен, и вызов станет дешевле. Если появились ошибки вида «Переменная не определена» для реквизитов формы — верните директиву с контекстом.

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

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

Проверка модуля в конфигураторе
Норма

Ошибок компиляции нет

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

Сообщения «Переменная не определена» для реквизитов формы

Поведение формы при вызове
Норма

Данные возвращаются, форма не перерисовывается целиком

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

Заметная задержка, мерцание формы при каждом вызове

Количество серверных вызовов
Норма

Один вызов на действие пользователя

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

Вызов внутри цикла по строкам таблицы

Альтернатива: вынос логики в общие модули

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

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

Влияние на производительность

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

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

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

Часто задаваемые вопросы

Можно ли вызвать процедуру НаСервереБезКонтекста из другой серверной процедуры?

Да. С сервера доступны процедуры обеих серверных директив. А вот с клиента нельзя вызвать процедуру &НаКлиентеНаСервереБезКонтекста, если она не объявлена доступной, и нельзя вызвать клиентскую процедуру с сервера — сервер не имеет доступа к клиентскому контексту.

Почему возникает ошибка «Переменная не определена (Объект)»?

Процедура объявлена с директивой &НаСервереБезКонтекста, а внутри идёт обращение к основному реквизиту формы. Либо смените директиву на &НаСервере, либо передавайте нужные данные параметром.

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

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

Чем отличается НаСервереБезКонтекста от общего серверного модуля?

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

Работает ли директива в обычных формах?

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

Влияет ли директива на права доступа?

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

Итог

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

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