К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как вызвать клиентскую процедуру с сервера в 1С

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

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

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

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

Почему сервер не может вызвать клиентскую процедуру

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

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

Способ 1. Вернуть результат из серверной функции и обработать на клиенте

Самый частый и правильный приём: клиент вызывает серверную функцию, та выполняет работу и возвращает структуру с результатом, а клиент по этим данным решает, что показать или открыть. Фактически «вызов клиентской логики с сервера» здесь заменяется передачей команды через возвращаемое значение.

&НаСервере

Функция ПровестиДокументНаСервере(Ссылка)

Результат = Новый Структура;

Результат.Вставить("Успешно", Истина);

Результат.Вставить("ТекстСообщения", "Документ проведён");

Результат.Вставить("НужноОткрытьОтчет", Ложь);

// ... логика проведения ...

Возврат Результат;

КонецФункции

&НаКлиенте

Процедура Провести(Команда)

Результат = ПровестиДокументНаСервере(Объект.Ссылка);

Если Результат.Успешно Тогда

ПоказатьПредупреждение(, Результат.ТекстСообщения);

Если Результат.НужноОткрытьОтчет Тогда

ОткрытьФорму("Отчет.Продажи.Форма");

КонецЕсли;

КонецЕсли;

КонецПроцедуры

Возвращать можно только сериализуемые типы: примитивы, структуры, массивы, таблицы значений, ссылки. Нельзя вернуть элемент формы, COM-объект или несериализуемый объект — получите ошибку преобразования данных. Если данных много, упакуйте их в структуру и отдавайте одним объектом, чтобы не плодить серверные вызовы.

Способ 2. Оповещения форм: Оповестить и ОбработкаОповещения

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

&НаКлиенте

Процедура ЗаписатьИОповестить(Команда)

ЗаписатьНаСервере();

Оповестить("ИзмененСтатусЗаказа", Объект.Ссылка, ЭтотОбъект);

КонецПроцедуры

// В другой форме:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ИзмененСтатусЗаказа" Тогда

Элементы.Список.Обновить();

КонецЕсли;

КонецПроцедуры

Для стандартных изменений данных есть ОповеститьОбИзменении(Ссылка) — эта процедура доступна и на сервере, и автоматически обновляет динамические списки и открытые формы объекта. Это ближайший аналог «вызова клиента с сервера»: сервер помечает данные как изменённые, а платформа сама уведомляет клиентские формы.

Способ 3. Фоновые задания с оповещением о завершении

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

&НаКлиенте

Процедура ЗапуститьОбработку(Команда)

ПараметрыПроцедуры = Новый Структура("Период", Период);

Оповещение = Новый ОписаниеОповещения("ПослеЗавершенияОбработки", ЭтотОбъект);

НачатьВыполнениеДлительнойОперации(Оповещение, ПараметрыПроцедуры);

КонецПроцедуры

&НаКлиенте

Процедура ПослеЗавершенияОбработки(Результат, ДопПараметры) Экспорт

Если Результат.Статус = "Выполнено" Тогда

Данные = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);

ПоказатьПредупреждение(, "Обработка завершена");

Иначе

ПоказатьПредупреждение(, "Ошибка: " + Результат.КраткоеПредставлениеОшибки);

КонецЕсли;

КонецПроцедуры

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

Порядок действий для длительной операции
  1. 1
    На клиенте сформируйте параметры и создайте ОписаниеОповещения с именем процедуры-обработчика
  2. 2
    Запустите фоновое задание (длительную операцию), передав параметры и оповещение
  3. 3
    В серверной процедуре выполните работу и поместите результат во временное хранилище
  4. 4
    В клиентской процедуре-обработчике проверьте статус и заберите результат из хранилища
  5. 5
    Покажите пользователю итог или сообщение об ошибке

Способ 4. Обработчик ожидания и периодический опрос

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

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

Способ 5. Система взаимодействия и обсуждения

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

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

Сравнение способов

Возврат значения из серверной функции

Универсальный вариант, когда клиент сам инициирует действие. Ограничение: работает только синхронно, клиент ждёт ответа.

Оповестить / ОбработкаОповещения

Подходит для синхронизации открытых форм. Ограничение: работает только внутри одного клиентского сеанса.

Фоновое задание с оповещением

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

Обработчик ожидания

Для реакции на внешние события. Ограничение: нагрузка на сервер и задержка реакции на интервал опроса.

Система взаимодействия

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

Типичные ошибки и как их избежать

Наиболее частая ошибка — попытка вызвать процедуру с директивой &НаКлиенте из общего модуля с флагом «Сервер». Конфигуратор отловит это при проверке, но если общий модуль имеет флаги «Клиент» и «Сервер» одновременно, ошибка всплывёт только в рантайме. Разделяйте общие модули по контекстам и не смешивайте вызовы.

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

Типичные ошибки
01
Вызов клиентской процедуры из серверного общего модуля — падение в рантайме или ошибка проверки конфигурации
02
Возврат из серверной функции несериализуемых объектов (элементы формы, COM) — ошибка преобразования данных
03
Десятки мелких серверных вызовов в цикле вместо одного пакетного — заметные тормоза интерфейса
04
Не отключённый обработчик ожидания после закрытия формы — лишние вызовы сервера и ошибки обращения к закрытой форме
05
Игнорирование статуса фонового задания — пользователь видит пустой результат вместо сообщения об ошибке
Контрольные точки

Как проверить результат

Вызов серверной процедуры
Норма

Клиент получает структуру с ожидаемыми полями, ошибок нет

Тревожный признак

Ошибка преобразования данных или пустое значение

Оповещение форм
Норма

ОбработкаОповещения срабатывает в целевой форме, список обновляется

Тревожный признак

Событие не приходит — проверьте имя события и что форма открыта

Фоновое задание
Норма

Статус «Выполнено», данные читаются из хранилища

Тревожный признак

Статус «Ошибка» или пустой адрес результата

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

Итог

Что важно запомнить

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

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

Можно ли обойти ограничение и всё-таки вызвать клиентскую процедуру с сервера?

Нет, платформа не предоставляет такого механизма, и обходных путей на уровне встроенного языка не существует. Любая схема сводится к тому, что клиент сам запрашивает сервер или подписывается на событие. Проектируйте логику исходя из этого, а не ищите хак.

Почему Оповестить на сервере недоступно, а ОповеститьОбИзменении — доступно?

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

Как передать с сервера на клиент таблицу значений?

Таблица значений сериализуется и может быть возвращена из серверной функции или помещена во временное хранилище. Для больших объёмов предпочтительнее хранилище: сервер кладёт данные через ПоместитьВоВременноеХранилище, клиент забирает по адресу. Учитывайте, что на клиенте с таблицей удобнее работать как с коллекцией строк, а при необходимости отобразить её в форме — преобразовать в данные формы.

Чем отличается ВызватьИсключение на сервере для клиента?

Исключение, возникшее в серверной процедуре, передаётся на клиент как ошибка вызова с текстом причины. Клиентская сторона должна обрабатывать такие ситуации через Попытка/Исключение и показывать пользователю понятное сообщение, а не технический текст. В фоновых заданиях текст ошибки приходит в свойстве результата.

Работает ли обработчик ожидания в веб-клиенте?

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

Как понять, что пора выносить операцию в фоновое задание?

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