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

· 9 мин

Содержание

Серверную процедуру из клиента в 1С 8.3 вызывают через директиву компиляции &НаСервере или &НаСервереБезКонтекста в модуле управляемой формы, либо через метод общего модуля, у которого в свойствах включён флажок «Вызов сервера». Клиентский код просто обращается к этому методу по имени — платформа сама выполняет его на сервере и возвращает результат. Это прямой вызов, и в 90% задач хватает именно его.

Остальные способы нужны в особых случаях. Долгий расчёт выносят в фоновое задание, чтобы не морозить форму. Вызов из сторонней программы делают через HTTP-сервис. Доработку без снятия типовой с поддержки оформляют расширением конфигурации. А запуск по расписанию, без участия пользователя, — регламентным заданием.

Ниже — все пять механизмов с кодом и границами применимости. Весь материал про управляемое приложение (интерфейс «Такси») платформы 8.3.

Что происходит, когда клиент обращается к серверу

В управляемом приложении код физически исполняется в двух местах: на тонком клиенте и на сервере 1С. Клиент рисует формы и реагирует на действия пользователя, а работа с базой — запросы, запись документов, проведение — доступна только на сервере.

Переход между ними называют серверным вызовом. Каждый такой вызов — это сетевой обмен: клиент упаковывает данные, отправляет их на сервер, ждёт ответ. Отсюда главное правило производительности: серверных вызовов должно быть как можно меньше, а данные лучше передавать пачкой, а не по одному значению в цикле.

На клиенте недоступны запросы к базе, менеджеры объектов, чтение и запись документов и справочников — всё это живёт только на сервере. Поэтому почти любая осмысленная работа с данными рано или поздно упирается в серверный вызов, и вопрос лишь в том, каким из способов ниже его оформить.

Где исполнится процедура, определяет директива компиляции:

  • 🖥️ &НаКлиенте — выполняется на клиенте, есть доступ к интерактивным методам и элементам формы;
  • 🗄️ &НаСервере — выполняется на сервере и имеет полный доступ к данным формы (контексту), но за это контекст гоняется туда и обратно;
  • ⚡ &НаСервереБезКонтекста — тоже на сервере, но без данных формы: вызов легче и быстрее;
  • 🔁 &НаКлиентеНаСервереБезКонтекста — один и тот же текст компилируется и для клиента, и для сервера.

Если серверной процедуре не нужны реквизиты формы, всегда берите &НаСервереБезКонтекста. Передача контекста формы — самая частая причина «тормозов» на тонком клиенте и в веб-клиенте.

Способ 1. Прямой вызов через директивы и общий модуль

Это и есть тот самый «DirectCall»: клиентская процедура формы напрямую обращается к серверной процедуре той же формы.

&НаКлиенте
Процедура РассчитатьСкидку(Команда)
    Скидка = РассчитатьСкидкуНаСервере(Объект.Сумма, Объект.Контрагент);
    Сообщить("Скидка: " + Формат(Скидка, "ЧДЦ=2"));
КонецПроцедуры

&НаСервереБезКонтекста
Функция РассчитатьСкидкуНаСервере(Сумма, Контрагент)
    Запрос = Новый Запрос;
    // ... обращение к базе, расчёт ...
    Возврат РезультатРасчёта;
КонецФункции

Клиент вызывает РассчитатьСкидкуНаСервере, платформа исполняет её на сервере и возвращает число. Параметры передаются в сервер по значению, результат — обратно на клиент.

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

  1. Сервер — модуль компилируется для сервера;
  2. Вызов сервера — его экспортные методы можно вызывать из клиентского кода.

Тогда вызов выглядит так же просто:

&НаКлиенте
Процедура ОбновитьКурсыВалют(Команда)
    РаботаСКурсамиВалют.ЗагрузитьАктуальныеКурсы();
КонецПроцедуры

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

Серверный вызов копирует значения, а не передаёт их по ссылке. Если серверная процедура изменит переданный массив или структуру, на клиенте изменения не отразятся — возвращайте результат явно через Возврат или выходной параметр.

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

Способ 2. Фоновое задание для долгих операций

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

Фоновое задание запускают только на сервере, а исполняемый метод должен быть экспортной процедурой серверного общего модуля:

&НаСервереБезКонтекста
Функция ЗапуститьПересчёт(ПараметрыПересчёта)
    МассивПараметров = Новый Массив;
    МассивПараметров.Добавить(ПараметрыПересчёта);
    Задание = ФоновыеЗадания.Выполнить(
        "РасчётыСервер.ПересчитатьИтоги",
        МассивПараметров,
        ,
        "Пересчёт итогов за период");
    Возврат Задание.УникальныйИдентификатор;
КонецФункции

Клиент получает идентификатор и периодически проверяет состояние задания:

&НаСервереБезКонтекста
Функция ЗаданиеЗавершено(Идентификатор)
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
    Возврат Задание <> Неопределено
        И Задание.Состояние <> СостояниеФоновогоЗадания.Активно;
КонецФункции

Состояние принимает значения Активно, Завершено, ЗавершеноАварийно, Отменено — по ним строят индикатор на форме. Запущенное задание можно прервать методом Задание.Отменить(). Возвращаемое значение напрямую из фонового задания не приходит: результат складывают во временное хранилище, регистр или реквизит и забирают после завершения.

Если в конфигурации подключена Библиотека стандартных подсистем, не пишите цикл опроса вручную — там есть готовая подсистема «Длительные операции» с методами запуска и ожидания результата. Она сама покажет пользователю прогресс.

Нюанс файловой базы: фоновые задания в ней выполняются, но ограниченно — обычно по одному за раз и в рамках подключения. Полноценная параллельная работа заданий — только в клиент-серверном варианте.

Способ 3. HTTP-сервис для вызова извне

Предыдущие способы работают внутри самой 1С. Когда серверную процедуру нужно вызвать из другой программы — сайта, мобильного приложения, стороннего сервиса — публикуют HTTP-сервис.

Порядок такой:

  1. В конфигураторе в ветке «HTTP-сервисы» создаётся сервис, задаётся корневой URL.
  2. К сервису добавляются шаблоны URL, а к каждому шаблону — методы с типом HTTP-запроса (GET, POST, PUT, DELETE) и именем обработчика.
  3. Обработчик — функция в модуле сервиса, которая принимает запрос и возвращает ответ. Исполняется она на сервере 1С.
Функция ОстатокТовара(Запрос)
    Код = Запрос.ПараметрыЗапроса.Получить("code");
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки["Content-Type"] = "application/json; charset=utf-8";
    Ответ.УстановитьТелоИзСтроки("{""code"": """ + Код + """}");
    Возврат Ответ;
КонецФункции

Чтобы сервис стал доступен снаружи, базу публикуют на веб-сервере: в конфигураторе Администрирование → Публикация на веб-сервере (нужен установленный IIS или Apache). После этого внешний клиент дёргает процедуру обычным HTTP-запросом по адресу вида http://сервер/имя_базы/hs/корневой_url/....

Доступ закрывают авторизацией: в настройках публикации указывают, под какой учётной записью информационной базы отрабатывает запрос — обычно по логину и паролю, которые клиент передаёт в заголовке. Права этого пользователя и ограничивают, что сервис имеет право прочитать или записать.

Для обмена в формате SOAP вместо HTTP-сервиса создают Web-сервис — логика та же, но описание интерфейса отдаётся по WSDL.

Способ 4. Вызов из внешней обработки и расширения конфигурации

Иногда серверный код нужно выполнить, не трогая основную конфигурацию. Здесь два инструмента.

Внешняя обработка (.epf) открывается через Файл → Открыть или подключается как дополнительная обработка. Модули её формы и объекта поддерживают те же директивы: процедура с &НаСервере внутри обработки честно выполнится на сервере. Своих прав обработка не добавляет — работает под текущим пользователем и не меняет структуру базы, поэтому для разовых задач и диагностики это самый быстрый путь.

Расширение конфигурации (.cfe) — механизм появился в платформе 8.3.6. Расширение позволяет добавлять свои общие модули, формы и методы, не снимая типовую с поддержки. В нём доступны аннотации, которыми вклиниваются в существующие методы:

  • &Перед — выполнить свой код перед типовым методом;
  • &После — после него;
  • &Вместо — полностью заменить типовой метод.

Так в типовую конфигурацию встраивают собственные серверные процедуры без правки оригинала.

Есть и третий путь вызвать серверный код из внешней программы — внешнее соединение через COM-коннектор. Стороннее приложение создаёт объект V83.COMConnector, подключается к базе и дёргает экспортные методы общих модулей, у которых включён флажок «Внешнее соединение». Способ рабочий, но тяжеловесный и привязан к Windows, поэтому для новых интеграций обычно предпочитают HTTP-сервис.

Загрузка .cfe и обновление конфигурации базы — два разных шага. После добавления расширения обязательно выполните обновление конфигурации базы данных, иначе новые методы в базе не появятся.

Способ 5. Регламентное задание для запуска по расписанию

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

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

Где выполняется расписание:

  • в клиент-серверной базе регламентные задания запускает планировщик кластера серверов — независимо от того, работает кто-то в базе или нет;
  • в файловой базе их выполняет сеанс пользователя, поэтому расписание отрабатывает, только пока база открыта.

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

Как выбрать способ

СпособКогда применятьВнешний клиент
Директивы и общий модульобычная логика формы, нужен быстрый ответнет
Фоновое заданиедолгий расчёт, чтобы не морозить формунет
HTTP-сервисвызов из сайта, мобильного или сторонней программыда
Внешняя обработка / расширениедоработка без правки типовойнет
Регламентное заданиезапуск по расписанию без пользователянет
Проверьте себя
Серверной процедуре не нужны реквизиты формы. Какую директиву выбрать?
Откуда запускается фоновое задание?
Чем вызвать серверную процедуру из стороннего сайта?

Типичные ошибки

🔸 «Переменная не определена (ИмяМодуля)» при вызове общего модуля с клиента. У модуля не включён флажок «Вызов сервера», поэтому на клиенте его просто не существует. Включите флажок либо вызывайте метод из серверной процедуры формы.

🔸 Обращение к Объект в процедуре &НаСервереБезКонтекста. Без контекста реквизиты формы недоступны. Передавайте нужные значения параметрами или переведите процедуру в &НаСервере, если контекст действительно нужен.

🔸 Сервер в цикле. Вызов серверной процедуры внутри цикла по строкам таблицы превращается в сотни сетевых обменов. Соберите данные в один массив или структуру и передайте за один вызов.

🔸 Фоновому заданию передана функция, а не процедура, или метод не экспортный. ФоновыеЗадания.Выполнить принимает имя экспортной процедуры серверного общего модуля — проверьте модификатор Экспорт и флажок «Сервер».

🔸 HTTP-сервис отвечает 404. База не опубликована на веб-сервере либо в адресе перепутан корневой URL. Проверьте публикацию и путь .../hs/....

🔸 Ожидание изменений в переданном объекте. Серверный вызов работает с копией значений: изменения массива или структуры на сервере на клиент сами не вернутся.

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

В чём разница между `&НаСервере` и `&НаСервереБезКонтекста`?
Обе выполняются на сервере, но &НаСервере получает полный контекст формы (её реквизиты гоняются на сервер и обратно), а &НаСервереБезКонтекста — нет. Без контекста вызов легче, поэтому его предпочитают, если данные формы не нужны.
Можно ли вызвать серверную процедуру прямо из команды формы?
Процедура-обработчик команды всегда &НаКлиенте. Из неё вызывают серверную процедуру той же формы или метод общего модуля с флажком «Вызов сервера» — напрямую из клиента серверный код не стартует.
Почему фоновое задание не запускается в файловой базе?
В файловом варианте фоновые задания ограничены: обычно выполняется одно за раз в рамках подключения. Полноценная параллельная работа заданий возможна только в клиент-серверной базе.
Чем HTTP-сервис отличается от Web-сервиса?
HTTP-сервис отвечает на произвольные HTTP-запросы и удобен для REST-обмена и JSON. Web-сервис работает по SOAP и отдаёт описание интерфейса в WSDL. Для вызова из современного сайта или мобильного приложения чаще берут HTTP-сервис.
Как добавить серверную процедуру в типовую, не снимая её с поддержки?
Через расширение конфигурации: создаёте в нём общий модуль со своей экспортной процедурой, при необходимости встраиваетесь в типовые методы аннотациями &Перед, &После или &Вместо, затем обновляете конфигурацию базы данных.