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

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

Как передать значение с сервера на клиент в 1С

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

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

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

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

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

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

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

Директивы компиляции определяют, где выполняется код: &НаКлиенте — на клиенте, &НаСервере — на сервере, &НаСервереБезКонтекста — на сервере без доступа к данным формы (работает быстрее, но не видит реквизиты формы напрямую).

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

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

// В модуле формы

&НаСервере

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

Запрос = Новый Запрос("ВЫБРАТЬ КоличествоОстаток ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки ГДЕ Номенклатура = &Номенклатура");

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

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

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

Возврат Выборка.КоличествоОстаток;

КонецЕсли;

Возврат 0;

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

&НаКлиенте

Процедура ПоказатьОстаток(Команда)

Остаток = ПолучитьОстатокНаСервере(ТекущаяНоменклатура);

ПоказатьОповещениеПользователя("Остаток: " + Остаток);

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

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

Способ 2. Передача нескольких значений через структуру

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

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

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

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

Результат.Вставить("Цена", 0);

Результат.Вставить("Остаток", 0);

Результат.Вставить("СтавкаНДС", Ссылка.СтавкаНДС);

// ... заполнение цены и остатка запросом ...

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

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

На клиенте поля структуры доступны как обычно: Данные.Цена, Данные.Остаток. Внутрь структуры можно вкладывать массивы, другие структуры, соответствия и таблицы значений — вложенность не ограничена, но каждый вложенный элемент тоже должен быть сериализуемым.

Способ 3. Передача таблицы значений и массива

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

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

Массивы и соответствия передаются аналогично. Типичный сценарий — серверная функция возвращает массив структур (список документов с реквизитами), а клиент выводит его пользователю или передаёт дальше.

Типичные ошибки
01
Попытка вернуть ДокументОбъект или СправочникОбъект на клиент — ошибка сериализации; передавайте ссылку или структуру с нужными полями
02
Возврат невыгруженного РезультатаЗапроса — сериализуется только Выгрузить() в таблицу значений
03
Множественные серверные вызовы в цикле на клиенте вместо одного вызова, возвращающего массив или таблицу
04
Передача таблицы с тысячами строк, когда клиенту нужны только итоги — считайте итоги на сервере

Способ 4. Временное хранилище для больших данных

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

&НаСервере

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

ТаблицаДанных = СформироватьБольшуюТаблицу();

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

Возврат Адрес;

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

&НаКлиенте

Процедура ОбработатьДанные(Команда)

Адрес = СформироватьДанныеНаСервере();

// Адрес можно передать в другую форму или использовать позже

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

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

Сравнение вариантов передачи

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

Примитивы, ссылки, небольшие структуры. Просто и быстро, но не подходит для больших объёмов

Структура / массив / таблица значений

Наборы данных умеренного размера. Универсально, но при тысячах строк начинает тормозить сериализация

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

Большие таблицы, двоичные данные, результаты СКД. Передаётся только адрес, данные забираются по требованию

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

Данные, которые отображаются в элементах формы. Платформа сама синхронизирует клиент и сервер

Передача данных между формами через сервер

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

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

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

Проверка результата и диагностика проблем

После передачи значения полезно убедиться, что клиент получил именно то, что ожидалось. Основные контрольные точки: тип значения, заполненность, объём данных.

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

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

Тип полученного значения
Норма

ТипЗнч() возвращает ожидаемый тип (Структура, ТаблицаЗначений, Число)

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

Неопределено или NULL — серверная функция не вернула значение или выбросила исключение

Содержимое структуры
Норма

Все ожидаемые ключи присутствуют, значения заполнены

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

Ключ отсутствует — ошибка в имени ключа или в логике заполнения на сервере

Данные из хранилища
Норма

ПолучитьИзВременногоХранилища возвращает данные ожидаемого типа

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

Возвращается Неопределено — хранилище очищено или адрес неверен

Ошибки сериализации
Норма

Вызов отрабатывает без исключений

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

Ошибка «Ошибка передачи данных между клиентом и сервером» — в значении есть несериализуемый тип

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

FAQ

Можно ли передать на клиент объект документа, чтобы изменить его на клиенте?

Нет, ДокументОбъект не сериализуется. На клиент передают ссылку, а изменения выполняют на сервере: клиент собирает данные в структуру, вызывает серверную процедуру, та получает объект по ссылке, изменяет и записывает его.

Что быстрее — вызов с контекстом или без контекста?

Вызов &НаСервереБезКонтекста быстрее, потому что платформа не передаёт на сервер данные формы. Разница заметна на формах с большими табличными частями и множеством реквизитов. Используйте вызовы без контекста везде, где данные формы не нужны.

Сколько живут данные во временном хранилище?

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

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

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

Почему таблица значений приходит на клиент пустой, хотя запрос вернул строки?

Чаще всего забыли вызвать Выгрузить() у результата запроса и вернули сам результат — при попытке сериализации возникает ошибка либо пустое значение. Проверьте, что функция возвращает именно Запрос.Выполнить().Выгрузить(), а не Выборку или РезультатЗапроса.

Можно ли передать данные с сервера на клиент без вызова из клиентского кода?

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

Итог

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

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