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

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

1С: как передать данные с сервера на клиента

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

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

Основные способы передачи: возврат значения из серверной процедуры или функции, параметры процедур, помещение данных во временное хранилище с передачей адреса, а также сериализация сложных объектов в строку (JSON или XML). Выбор зависит от объёма данных, их типа и частоты обращений.

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

Как устроен обмен между клиентом и сервером в 1С

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

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

Передача данных через возвращаемое значение серверной функции

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

&НаСервереБезКонтекста

Функция ПолучитьДанныеКонтрагента(Ссылка)

Запрос = Новый Запрос("ВЫБРАТЬ Наименование, ИНН, КПП

|ИЗ Справочник.Контрагенты ГДЕ Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", Ссылка);

Выборка = Запрос.Выполнить().Выбрать();

Результат = Новый Структура("Наименование,ИНН,КПП", "", "", "");

Если Выборка.Следующий() Тогда

ЗаполнитьЗначенияСвойств(Результат, Выборка);

КонецЕсли;

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

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

&НаКлиенте

Процедура КонтрагентПриИзменении(Элемент)

Данные = ПолучитьДанныеКонтрагента(Объект.Контрагент);

Объект.ИНН = Данные.ИНН;

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

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

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

Передача таблиц и больших объёмов данных через временное хранилище

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

&НаСервере

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

Таблица = ПолучитьТаблицуОстатков();

Возврат ПоместитьВоВременноеХранилище(Таблица, УникальныйИдентификатор);

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

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

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

Передача сложных объектов через сериализацию в JSON и XML

Если нужно передать произвольную вложенную структуру данных — например, результат обращения к внешнему API или дерево значений — удобно сериализовать её в строку JSON на сервере и разобрать на клиенте (или наоборот). Платформа предоставляет объекты ЗаписьJSON / ЧтениеJSON и функции работы с XDTO.

Такой подход также применяется, когда данные нужно сохранить в реквизит строкового типа, передать через веб-сервис или вернуть из HTTP-сервиса. Строка гарантированно сериализуема, поэтому обходит ограничения платформы, но требует явной упаковки и распаковки на обеих сторонах.

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

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

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

Подходит для структур, массивов и примитивов. Самый быстрый и читаемый способ; ограничение — только сериализуемые типы.

Временное хранилище

Для таблиц значений, двоичных данных, результатов отчётов. Требует управления временем жизни через УникальныйИдентификатор формы.

JSON/XML-строка

Для обмена с внешними системами и веб-сервисами. Универсально, но добавляет код упаковки/распаковки и накладные расходы.

Реквизиты формы

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

Асинхронная передача: длительные операции и фоновые задания

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

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

Даже без БСП можно использовать ФоновыеЗадания.Выполнить() напрямую, но тогда контроль завершения и обработку ошибок придётся реализовывать самостоятельно.

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

Типичные ошибки при передаче данных с сервера на клиент

Большинство проблем сводится к нескольким повторяющимся сценариям. Их знание экономит часы отладки.

Типичные ошибки
01
Возврат объекта (СправочникОбъект, ДокументОбъект) вместо структуры — вызов падает с ошибкой сериализации. Возвращайте ссылку или структуру с реквизитами.
02
Забытый второй параметр УникальныйИдентификатор в ПоместитьВоВременноеХранилище — данные удаляются сразу после вызова, клиент получает пустоту.
03
Множество мелких серверных вызовов в цикле на клиенте — форма тормозит. Собирайте данные пакетом одним вызовом.
04
Передача на сервер данных формы с последующим возвратом целиком — лишний трафик. Передавайте только идентификаторы и изменённые поля.
05
Использование &НаСервере вместо &НаСервереБезКонтекста там, где данные формы не нужны — платформа гоняет весь контекст формы туда-обратно без пользы.

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

Контрольные точки

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

Данные дошли до клиента
Норма

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

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

Переменная пуста или содержит Неопределено — проверяйте адрес хранилища и возврат функции

Нет лишних серверных вызовов
Норма

Один вызов на логическую операцию (замер через замер производительности)

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

Десятки вызовов в цикле — требуется пакетная передача

Объём передаваемых данных
Норма

Передаются только нужные поля и строки

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

Передаётся вся таблица или весь объект целиком

Поведение при ошибке
Норма

Клиент получает понятное сообщение об ошибке

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

Форма зависает или молча теряет данные

Контекстные и бесконтекстные серверные вызовы: что выбрать

Процедуры &НаСервере имеют доступ к данным формы, но за это приходится платить: при каждом вызове платформа сериализует данные формы на сервер и обратно. Для форм с большими табличными частями это ощутимые накладные расходы.

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

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

FAQ: частые вопросы о передаче данных с сервера на клиента

Можно ли вернуть таблицу значений из серверной функции напрямую?

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

Почему клиент получает пустые данные из временного хранилища?

Чаще всего не передан второй параметр — УникальныйИдентификатор формы — в ПоместитьВоВременноеХранилище. Без привязки к форме хранилище очищается после завершения серверного вызова. Также проверьте, что адрес не используется повторно после удаления данных.

Как передать на клиент картинку или файл с сервера?

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

Что быстрее: структура или временное хранилище?

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

Можно ли с сервера инициировать действие на клиенте?

В рамках одного вызова — нет, сервер только возвращает результат. Для инициирования действий со стороны сервера используются механизмы оповещений: клиент подписывается на оповещение, а другой сеанс или фоновое задание отправляет его. Также существуют интерактивные push-уведомления в мобильной платформе и расширенные механизмы взаимодействия в тонком клиенте.

Почему вызов &НаСервереБезКонтекста не видит реквизиты формы?

Это by design: бесконтекстный вызов не переносит данные формы на сервер, поэтому реквизиты и элементы формы в нём недоступны. Передайте нужные значения параметрами. Если данных много — соберите их в структуру на клиенте и передайте одним параметром.

Итог

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

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