Как определить контекст выполнения кода (клиент, сервер, фоновое задание) в 1С:Предприятии?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← К списку

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

Понимание контекстов выполнения в 1С:Предприятии

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

Директивы компиляции: Явное указание контекста

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

  1. &НаКлиенте: Если мы помечаем процедуру или функцию этой директивой, это означает, что код будет выполняться в контексте клиентского приложения (тонкий клиент, веб-клиент, толстый клиент в режиме управляемого приложения). В этом контексте нам доступны только элементы, параметры и реквизиты формы. Мы не можем напрямую обращаться к данным базы данных.

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

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

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

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

Если мы не указываем директиву, по умолчанию платформа установит &НаСервере. Это важно учитывать при разработке.

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

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

  1. Через параметры сеанса: Маркировка фоновых заданий

    Один из подходов, предложенных опытными разработчиками, заключается в использовании параметров сеанса. Мы можем завести специальный параметр сеанса, например, РаботаетРегламентноеЗаданиеТакоеТо (тип Булево). Перед запуском регламентного или фонового задания мы устанавливаем этот параметр в Истина на сервере, а по завершении — сбрасываем. Таким образом, любая серверная процедура, которая выполняется в рамках этого задания, сможет проверить значение этого параметра сеанса, чтобы понять, что она является частью фонового процесса. Это позволяет нам гибко управлять логикой в зависимости от того, вызван ли код интерактивно или в рамках автоматизированной задачи.

  2. Через функцию ПолучитьТекущийСеансИнформационнойБазы().ИмяПриложения: Определение фоновых заданий

    Это очень мощный и часто используемый способ, особенно для определения того, что код выполняется в фоновом задании. Функция ПолучитьТекущийСеансИнформационнойБазы() возвращает объект, который содержит информацию о текущем сеансе информационной базы. У этого объекта есть свойство ИмяПриложения, которое позволяет нам узнать, какое приложение инициировало текущий сеанс. Если значение этого свойства равно "BackgroundJob", это означает, что наш код выполняется в контексте фонового задания. Фоновые задания всегда выполняются на стороне сервера и не имеют возможности интерактивной работы с пользователем. Давайте посмотрим на пример:

    
    Процедура ВыполнитьДействиеНаСервере() Экспорт
        // Проверяем, что код выполняется в фоновом задании
        Если ПолучитьТекущийСеансИнформационнойБазы().ИмяПриложения = "BackgroundJob" Тогда
            // Безопасно вызываем паузу, так как это фоновое задание
            ВызватьПаузу(5); // Пауза на 5 секунд
        Иначе
            // Логика для клиент-серверного вызова, где пауза не нужна или нежелательна
            Сообщить("Метод ВызватьПаузу не используется в клиент-серверном вызове.");
        КонецЕсли;
        
        // Здесь размещается основной код, который должен выполняться в зависимости от контекста
        // ...
    КонецПроцедуры
    

    В этом примере мы видим, как удобно использовать ИмяПриложения для адаптации поведения кода. Если мы находимся в фоновом задании, мы можем, например, вызвать паузу, что недопустимо для интерактивного клиент-серверного вызова.

  3. С помощью предопределенных переменных препроцессора

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

    • #Если Клиент Тогда
    • #Если Сервер Тогда
    • #Если ВнешнееСоединение Тогда
    • #Если МобильноеПриложениеКлиент Тогда
    • #Если МобильноеПриложениеСервер Тогда

    Например:

    
    #Если Клиент Тогда
        // Код, который будет компилироваться только для клиента
        Сообщить("Выполняемся на клиенте!");
    #КонецЕсли
    
    #Если Сервер Тогда
        // Код, который будет компилироваться только для сервера
        Запрос = Новый Запрос("ВЫБРАТЬ ...");
        Результат = Запрос.Выполнить().Выгрузить();
    #КонецЕсли
    

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

  4. Анализируя СтрокаСоединенияИнформационнойБазы()

    Хотя этот метод не определяет контекст "клиент/сервер" в рамках одного приложения, он позволяет нам выяснить тип подключения к информационной базе. Это может быть полезно, например, для определения, работаем ли мы с файловой базой данных или с клиент-серверной. Если мы хотим проверить, является ли база файловой, мы можем использовать следующий подход:

    
    Если Лев(СтрокаСоединенияИнформационнойБазы(), 4) = "File" Тогда
        // Мы работаем с файловой базой
        Сообщить("Информационная база файловая.");
    Иначе
        // Мы работаем с клиент-серверной базой
        Сообщить("Информационная база клиент-серверная.");
    КонецЕсли;
    

    Функция СтрокаСоединенияИнформационнойБазы() возвращает строку, описывающую параметры подключения. Анализируя ее, мы можем делать выводы о текущей конфигурации.

Важные аспекты и рекомендации

Подводя итоги, хотим обратить ваше внимание на несколько дополнительных моментов, которые помогут нам в работе:

Мы надеемся, что этот подробный разбор поможет вам лучше ориентироваться в контекстах выполнения кода в 1С:Предприятии и создавать более надежные и эффективные решения. Удачи в разработке!

← К списку