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

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

Что значит «без контекста» в 1С

Что означает вызов «без контекста» в 1С:Предприятие, где применяется, чем отличается от контекстного вызова и как избежать типичных ошибок в коде.

Во встроенном языке 1С:Предприятие термин «без контекста» означает вызов процедуры или функции без привязки к конкретному объекту — форме, документу, записи регистра или элементу справочника. Такой вызов выполняется «в вакууме»: код не знает, из какой формы или объекта его запустили, и не имеет доступа к данным этого объекта напрямую.

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

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

Что такое контекст в 1С и почему его может не быть

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

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

Важно понимать, что «без контекста» — не синоним «на сервере». Это независимые характеристики: код может выполняться на сервере как с контекстом формы (директива &НаСервере в модуле формы), так и без него (&НаСервереБезКонтекста).

Директивы компиляции в модулях форм

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

ДирективаГде выполняетсяДоступ к реквизитам формы
&НаКлиентеНа клиентеЕсть (клиентский контекст формы)
&НаСервереНа сервереЕсть (форма передаётся на сервер)
&НаСервереБезКонтекстаНа сервереНет, данные передаются параметрами
&НаКлиентеНаСервереБезКонтекстаИ там, и тамНет, только параметры

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

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

Как выбрать директиву: практический маршрут

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

Маршрут решения

Как выбрать директиву

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

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

Общие модули и работа без контекста

Общие модули по своей природе работают без контекста формы: они не привязаны к конкретному объекту интерфейса. Флаги общего модуля («Сервер», «Клиент», «Вызов сервера», «Привилегированный режим») определяют, где компилируется и выполняется его код.

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

При передаче данных в серверный общий модуль учитывайте ограничение: между клиентом и сервером можно передавать только сериализуемые типы — примитивы, структуры, массивы, ссылки. Передать, например, объект ДанныеФормыСтруктура или таблицу значений напрямую нельзя; табличную часть обычно передают как массив структур или выгружают в значение через промежуточные механизмы.

bsl
&НаСервереБезКонтекста
Функция ПолучитьОстаток(Номенклатура, Склад)
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
	|ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура = &Номенклатура И Склад = &Склад) КАК Остатки";
	Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
	Запрос.УстановитьПараметр("Склад", Склад);
	Выборка = Запрос.Выполнить().Выбрать();
	Возврат ?(Выборка.Следующий(), Выборка.Остаток, 0);
КонецФункции

Фоновые задания и внешние вызовы

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

Аналогично работают HTTP-сервисы, веб-сервисы и планы обмена: входящий вызов обрабатывается вне какого-либо пользовательского контекста. Все необходимые данные извлекаются из тела запроса, параметров или заголовков.

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

Типичные ошибки и как их диагностировать

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

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

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

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

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

Компиляция модуля формы
Норма

Нет ошибок «переменная не определена»

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

Ошибки на реквизиты формы в процедурах без контекста

Состав параметров серверной процедуры
Норма

Передаются только нужные ссылки и значения

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

Передаётся вся форма ради одного поля

Возвращаемое значение
Норма

Сериализуемый тип: структура, массив, ссылка, примитив

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

Попытка вернуть объект данных или элемент формы

Практические рекомендации

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

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

Итог

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

«Без контекста» — это выполнение кода без привязки к объекту: данные доступны только через параметры. Директива &НаСервереБезКонтекста ускоряет серверные вызовы, но требует явной передачи данных. Общие модули, фоновые задания и сервисы всегда работают без контекста формы.

Частые вопросы

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

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

Почему возникает ошибка «Переменная не определена» в процедуре формы?

Чаще всего процедура помечена директивой без контекста, а внутри неё идёт обращение к реквизиту формы по имени. Либо измените директиву на контекстную, либо передайте нужное значение параметром.

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

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

Какие типы данных можно передавать между клиентом и сервером?

Примитивные типы (строка, число, дата, булево), ссылки, структуры, массивы, соответствия и некоторые сериализуемые коллекции. Объекты данных (ДокументОбъект, ДанныеФормы) передавать нельзя — передавайте ссылку и получайте объект на сервере.

Почему фоновое задание не видит данные открытой формы?

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

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

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