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