Разработка и Конфигурация · 12 мин
1С: как передать данные с сервера на клиента
Как в 1С передать данные с сервера на клиента: возврат значений из серверных процедур, структуры, временное хранилище, сериализация и типичные ошибки разработчиков.
В управляемых формах 1С код выполняется в двух контекстах: на клиенте и на сервере. Обмен данными между ними строго регламентирован платформой: клиент не может напрямую читать базу данных, а сервер не имеет доступа к элементам интерфейса. Поэтому передача данных с сервера на клиента — одна из базовых задач при разработке управляемых форм, обработок и веб-сервисов.
Основные способы передачи: возврат значения из серверной процедуры или функции, параметры процедур, помещение данных во временное хранилище с передачей адреса, а также сериализация сложных объектов в строку (JSON или XML). Выбор зависит от объёма данных, их типа и частоты обращений.
Важно понимать ограничение платформы: через границу «сервер — клиент» можно передавать только сериализуемые значения. Примитивные типы, структуры, массивы, таблицы значений (с оговорками) передаются свободно, а объекты типа СправочникОбъект, запросы, менеджеры временных таблиц — нет. Попытка вернуть несериализуемый объект приведёт к ошибке вызова.
Как устроен обмен между клиентом и сервером в 1С
Каждый вызов серверной процедуры из клиентского кода — это отдельный серверный вызов, который в клиент-серверном варианте означает сетевой обмен. Платформа упаковывает переданные параметры, выполняет код на сервере и возвращает результат. Чем больше таких вызовов и чем тяжелее передаваемые данные, тем заметнее просадка производительности формы.
Директивы компиляции определяют, где выполняется код: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста. Клиентская процедура может вызвать серверную, но не наоборот — сервер не может инициировать обращение к клиенту в рамках того же вызова. Обратная связь возможна только через возвращаемое значение или через механизм оповещений после завершения серверного вызова.
Передача данных через возвращаемое значение серверной функции
Самый простой и рекомендуемый способ — вернуть значение из серверной функции. На клиенте создаётся вызов, серверная функция формирует результат и возвращает его. Для нескольких значений используйте структуру.
&НаСервереБезКонтекста
Функция ПолучитьДанныеКонтрагента(Ссылка)
Запрос = Новый Запрос("ВЫБРАТЬ Наименование, ИНН, КПП
|ИЗ Справочник.Контрагенты ГДЕ Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Результат = Новый Структура("Наименование,ИНН,КПП", "", "", "");
Если Выборка.Следующий() Тогда
ЗаполнитьЗначенияСвойств(Результат, Выборка);
КонецЕсли;
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
Данные = ПолучитьДанныеКонтрагента(Объект.Контрагент);
Объект.ИНН = Данные.ИНН;
КонецПроцедуры
Обратите внимание: на сервер передаётся ссылка, а не объект. Ссылки сериализуются корректно, поэтому типовой шаблон — «передать ссылку на сервер, получить назад структуру с реквизитами». Никогда не пытайтесь вернуть СправочникОбъект — вызов завершится ошибкой.
Если из клиентской процедуры нужно несколько реквизитов одного объекта, получайте их одним серверным вызовом через структуру, а не отдельными функциями на каждый реквизит. Три вызова по одному полю — это три сетевых обращения вместо одного.
Передача таблиц и больших объёмов данных через временное хранилище
Таблицу значений вернуть из серверной функции напрямую нельзя в общем случае — она не сериализуется для передачи на клиент. Стандартное решение — поместить данные во временное хранилище на сервере и вернуть клиенту адрес хранилища. Клиент при необходимости извлекает данные методом ПолучитьИзВременногоХранилища() в другом серверном вызове либо передаёт адрес дальше (например, в компоновщик настроек отчёта).
&НаСервере
Функция СформироватьДанныеНаСервере()
Таблица = ПолучитьТаблицуОстатков();
Возврат ПоместитьВоВременноеХранилище(Таблица, УникальныйИдентификатор);
КонецФункции
Второй параметр — уникальный идентификатор формы — важен: он привязывает хранилище к времени жизни формы. Без него данные удалятся после завершения серверного вызова, и клиент получит пустой результат. Это одна из самых частых причин «пропадающих» данных.
Для табличных частей формы хранилище обычно не нужно: данные реквизитов формы платформа передаёт между клиентом и сервером автоматически. Хранилище оправдано для отчётов, результатов загрузки файлов, обмена между формами и передачи данных в фоновые задания.
Передача сложных объектов через сериализацию в JSON и XML
Если нужно передать произвольную вложенную структуру данных — например, результат обращения к внешнему API или дерево значений — удобно сериализовать её в строку JSON на сервере и разобрать на клиенте (или наоборот). Платформа предоставляет объекты ЗаписьJSON / ЧтениеJSON и функции работы с XDTO.
Такой подход также применяется, когда данные нужно сохранить в реквизит строкового типа, передать через веб-сервис или вернуть из HTTP-сервиса. Строка гарантированно сериализуема, поэтому обходит ограничения платформы, но требует явной упаковки и распаковки на обеих сторонах.
Для типовых задач внутри одной конфигурации JSON обычно избыточен: структуры и массивы передаются напрямую. Сериализацию в строку выбирайте, когда получатель данных — внешняя система, веб-клиент с ограничениями или когда формат данных нужно зафиксировать независимо от версии платформы.
Сравнение способов передачи
Подходит для структур, массивов и примитивов. Самый быстрый и читаемый способ; ограничение — только сериализуемые типы.
Для таблиц значений, двоичных данных, результатов отчётов. Требует управления временем жизни через УникальныйИдентификатор формы.
Для обмена с внешними системами и веб-сервисами. Универсально, но добавляет код упаковки/распаковки и накладные расходы.
Для данных, отображаемых в интерфейсе. Платформа синхронизирует их автоматически, отдельная передача не нужна.
Асинхронная передача: длительные операции и фоновые задания
Если серверная операция занимает заметное время, синхронный вызов заблокирует интерфейс пользователя. Правильный подход — механизм длительных операций БСП (или фоновые задания напрямую): клиент запускает задание, сервер выполняет его в фоне, а результат помещает во временное хранилище. Клиент периодически проверяет состояние и по завершении забирает данные по адресу.
Схема выглядит так: серверная функция запуска вызывает ДлительныеОперации.ВыполнитьВФоне(), получает структуру с адресом результата и идентификатором задания, возвращает её клиенту. Клиент подключает обработчик ожидания и по завершении вызывает серверную процедуру, которая извлекает данные из хранилища и обновляет форму.
Даже без БСП можно использовать ФоновыеЗадания.Выполнить() напрямую, но тогда контроль завершения и обработку ошибок придётся реализовывать самостоятельно.
- 1На сервере запустите длительную операцию, указав процедуру-обработчик и параметры
- 2В обработчике поместите результат во временное хранилище (ПоместитьВоВременноеХранилище)
- 3Верните клиенту адрес хранилища и идентификатор задания
- 4На клиенте настройте ожидание завершения (ОписаниеОповещения, обработчик ожидания)
- 5После завершения в серверном вызове получите данные по адресу и обновите форму
- 6Проверьте, что при ошибке задания клиент получает текст ошибки, а не зависает в ожидании
Типичные ошибки при передаче данных с сервера на клиент
Большинство проблем сводится к нескольким повторяющимся сценариям. Их знание экономит часы отладки.
Отдельно стоит упомянуть попытку «вернуть» данные через глобальные переменные или параметры сеанса. Параметры сеанса предназначены для данных, фиксированных на время сеанса (текущий пользователь, настройки), а не для передачи результатов вызовов — такое использование приводит к неочевидным ошибкам при параллельной работе.
Как проверить результат
Переменная на клиенте содержит ожидаемые значения после вызова
Переменная пуста или содержит Неопределено — проверяйте адрес хранилища и возврат функции
Один вызов на логическую операцию (замер через замер производительности)
Десятки вызовов в цикле — требуется пакетная передача
Передаются только нужные поля и строки
Передаётся вся таблица или весь объект целиком
Клиент получает понятное сообщение об ошибке
Форма зависает или молча теряет данные
Контекстные и бесконтекстные серверные вызовы: что выбрать
Процедуры &НаСервере имеют доступ к данным формы, но за это приходится платить: при каждом вызове платформа сериализует данные формы на сервер и обратно. Для форм с большими табличными частями это ощутимые накладные расходы.
Директива &НаСервереБезКонтекста выполняется без передачи данных формы — вызов легче и быстрее. Правило простое: если процедуре не нужны реквизиты формы, объявляйте её бесконтекстной и передавайте нужные значения параметрами. Код становится чище, а производительность — предсказуемее.
В общих модулях с флагом «Сервер» размещайте бизнес-логику, вызываемую из форм: это убирает дублирование и позволяет переиспользовать код из разных объектов. Флаг «Вызов сервера» ставьте только там, где модуль действительно должен вызываться с клиента — это вопрос не только архитектуры, но и безопасности, так как такие методы доступны извне.
FAQ: частые вопросы о передаче данных с сервера на клиента
Можно ли вернуть таблицу значений из серверной функции напрямую?
Нет, таблица значений не сериализуется для передачи на клиент. Поместите её во временное хранилище и верните адрес, либо преобразуйте в массив структур, если объём данных небольшой. Для отображения в форме используйте реквизит формы типа «ТаблицаЗначений» — платформа синхронизирует его сама.
Почему клиент получает пустые данные из временного хранилища?
Чаще всего не передан второй параметр — УникальныйИдентификатор формы — в ПоместитьВоВременноеХранилище. Без привязки к форме хранилище очищается после завершения серверного вызова. Также проверьте, что адрес не используется повторно после удаления данных.
Как передать на клиент картинку или файл с сервера?
Поместите двоичные данные во временное хранилище на сервере и верните адрес. На клиенте адрес можно назначить реквизиту формы, связанному с полем картинки, или извлечь данные для сохранения в файл. Передавать двоичные данные внутри структуры не стоит при больших размерах.
Что быстрее: структура или временное хранилище?
Для небольших наборов значений структура быстрее и проще — данные возвращаются в том же вызове. Хранилище оправдано для таблиц, двоичных данных и больших объёмов, а также когда результат нужен нескольким получателям или должен пережить отдельные вызовы.
Можно ли с сервера инициировать действие на клиенте?
В рамках одного вызова — нет, сервер только возвращает результат. Для инициирования действий со стороны сервера используются механизмы оповещений: клиент подписывается на оповещение, а другой сеанс или фоновое задание отправляет его. Также существуют интерактивные push-уведомления в мобильной платформе и расширенные механизмы взаимодействия в тонком клиенте.
Почему вызов &НаСервереБезКонтекста не видит реквизиты формы?
Это by design: бесконтекстный вызов не переносит данные формы на сервер, поэтому реквизиты и элементы формы в нём недоступны. Передайте нужные значения параметрами. Если данных много — соберите их в структуру на клиенте и передайте одним параметром.
Что важно запомнить
Передача данных с сервера на клиент в 1С выполняется через возвращаемые значения серверных функций (структуры, массивы, примитивы), временное хранилище для таблиц и двоичных данных, либо сериализацию в JSON для внешних систем. Объекты базы данных передавать нельзя — только ссылки и структуры. Минимизируйте число серверных вызовов, используйте бесконтекстные процедуры и длительные операции для тяжёлых задач, и всегда проверяйте права и входные параметры на сервере.