Как вызвать серверный метод из клиентского контекста и прочитать константу в 1С 8.3?

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

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

Почему не сработал общий модуль с флагами «Клиент» и «Сервер»?

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

Давайте проанализируем, как это устроено изнутри платформы 1С:

  1. Когда у общего модуля включены оба флага (клиентский и серверный), платформа компилирует этот модуль дважды — отдельно для клиента и отдельно для сервера. Такие модули называют клиент-серверными (например, ОбщегоНазначенияКлиентСервер).
  2. Если вы вызываете экспортную функцию такого модуля из клиентского контекста, платформа выполняет её клиентскую сборку. Физического перехода выполнения кода на сервер при этом не происходит.
  3. Так как код выполняется на клиенте, в нем по-прежнему недоступен серверный контекст. Попытка прочитать константу, выполнить запрос или обратиться к менеджеру справочника вызовет критическую ошибку выполнения, поскольку клиентский сеанс «не знает» о существовании серверных типов данных и таблиц БД напрямую.

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

Решение 1: Использование общего модуля с флагом «Вызов сервера»

Наиболее очевидным решением для вызова серверной логики (в нашем случае — чтения константы) из клиентского модуля является создание или использование специального общего модуля, выполняющего роль «моста» между клиентом и сервером.

Разберем по шагам, как правильно настроить такой модуль согласно стандартам разработки фирмы 1С:

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

Посмотрим на пример реализации кода в модуле ОбщегоНазначенияВызовСервера:


Функция ПолучитьЗначениеКонстантыИспользоватьИнтеграцию() Экспорт
    Возврат Константы.ИспользоватьИнтеграциюCRM.Получить();
КонецФункции

Теперь в вашем клиентском общем модуле вы можете легко вызвать эту функцию и получить значение константы на клиенте перед открытием формы:


Процедура ОбработатьСобытиеНаКлиенте() Экспорт
    
    // Вызываем серверный модуль через механизм "Вызов сервера"
    ИспользоватьCRM = ОбщегоНазначенияВызовСервера.ПолучитьЗначениеКонстантыИспользоватьИнтеграцию();
    
    Если ИспользоватьCRM Тогда
        // Открываем форму интерактивно
        ОткрытьФорму("ОбщийФорма.ФормаИнтеграцииCRM");
    Иначе
        // Выполняем альтернативную логику
        ПоказатьПредупреждение(, "Интеграция с CRM отключена в настройках системы!");
    КонецЕсли;
    
КонецПроцедуры

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

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

Решение 2: Использование функциональных опций (самый быстрый и правильный способ)

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

Платформа 1С предоставляет изящное альтернативное решение — Функциональные опции (ФО). Рассмотрим этот механизм подробнее:

  1. В конфигураторе создайте новый объект метаданных Функциональная опция (например, ИспользоватьИнтеграциюCRM).
  2. В свойствах созданной функциональной опции в поле «Хранилище» укажите вашу константу.
  3. В коде клиентского модуля вызовите встроенную функцию платформы ПолучитьФункциональнуюОпцию().

Посмотрим на пример клиентского кода с использованием функциональной опции:


Процедура ОбработатьСобытиеНаКлиентеБыстро() Экспорт
    
    // Получаем значение константы мгновенно без обращения к серверу БД!
    Если ПолучитьФункциональнуюОпцию("ИспользоватьИнтеграциюCRM") Тогда
        ОткрытьФорму("ОбщийФорма.ФормаИнтеграцииCRM");
    КонецЕсли;
    
КонецПроцедуры

Почему это работает быстрее? Значения функциональных опций кэшируются платформой 1С на стороне клиента в момент запуска сеанса пользователя. При вызове метода ПолучитьФункциональнуюОпцию() система считывает данные мгновенно из локальной оперативной памяти клиента без выполнения реального сетевого запроса к серверу. Кэш обновляется автоматически при изменении константы или принудительно с помощью метода ОбновитьИнтерфейс().

Критическая ошибка логики: Внешнее соединение и открытие форм

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

Выясним причину, почему это не будет работать:

Как правильно решить эту задачу? Логика должна быть строго разделена. Внешнее соединение должно лишь записывать полученные данные в базу данных (например, в специальный регистр сведений «ОчередьСобытий» или «ЗадачиПользователей»). А на стороне активного клиентского приложения пользователя должен работать обработчик ожидания или система взаимодействия, которая периодически опрашивает этот регистр и при обнаружении новой записи интерактивно открывает форму на экране конкретного пользователя.

← На главную