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

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

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

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

Проанализируем ситуацию, описанную в теме. Ошибка {МодульУправляемогоПриложения(3,14)}: Переменная не определена (КоннекторHTTP) возникает во время проверки кода в режиме «Тонкий клиент». Это ключевой момент для понимания архитектуры 1С. Разберем по шагам, что происходит в системе:

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

Различие между модулем приложения и модулями форм

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

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

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

Решение проблемы: правильная организация вызова

Для того чтобы вызвать метод серверного общего модуля из модуля управляемого приложения, необходимо создать «мостик». Рассмотрим этот процесс пошагово.

Шаг 1. Проверка флагов общего модуля. Прежде всего, убедимся, что модуль расширения настроен правильно. Если нам нужен доступ с клиента, у модуля должны стоять галочки:

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

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

Шаг 3. Написание кода-посредника. В созданном модуле напишем экспортную функцию, которая будет обращаться к нашей библиотеке:


Функция ПолучитьДанныеHTTP(Параметры) Экспорт
    // Здесь серверный контекст, библиотека КоннекторHTTP доступна
    Результат = КоннекторHTTP.GetJson(Параметры);
    Возврат Результат;
КонецФункции

Шаг 4. Вызов из модуля управляемого приложения. Теперь в процедуре ПриНачалеРаботыСистемы мы вызываем не библиотеку напрямую, а наш промежуточный модуль:


Процедура ПриНачалеРаботыСистемы()
    Результат = РаботаСЗапросамиСервер.ПолучитьДанныеHTTP("https://api.example.com");
    Сообщить(Результат);
КонецПроцедуры

Использование инструкций препроцессора

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


Процедура ПриНачалеРаботыСистемы()
    #Если Сервер Или ТолстыйКлиентОбычноеПриложение Тогда
        Результат = КоннекторHTTP.GetJson("https://api.example.com");
        Сообщить(Результат);
    #КонецЕсли
КонецПроцедуры

В этом случае при проверке для Тонкого клиента компилятор просто проигнорирует блок кода внутри #Если...#КонецЕсли, и ошибка «Переменная не определена» исчезнет. Однако помните, что в реальном Тонком клиенте этот код просто не выполнится.

Загадка имен: БОНД_Коннектор или КоннекторHTTP?

Проанализируем еще один интересный вопрос из обсуждения: почему в дереве конфигурации модуль называется БОНД_Коннектор, а в коде к нему обращаются как КоннекторHTTP?

Это стандартный прием для профессиональных библиотек. Чтобы упростить жизнь пользователю и скрыть сложные префиксы, разработчики используют механизм псевдонимов. Обычно это реализуется одним из двух способов:

  1. Глобальная переменная: В модуле расширения (например, в процедуре ПриУстановкеПараметровСеанса) или в глобальном модуле создается переменная, которой присваивается ссылка на модуль: КоннекторHTTP = БОНД_Коннектор;.
  2. Экспортная функция: Создается короткая функция в глобальном контексте, которая возвращает ссылку на нужный модуль.

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

Резюме

Подводя итоги, при работе с расширениями и внешними библиотеками в 1С 8.3 помните следующее:

← На главную