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

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

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

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

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

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

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

Почему результат запроса нельзя вернуть «как есть»

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

Та же проблема возникает с объектом «ВыборкаИзРезультатаЗапроса»: обход выборки возможен только в серверном контексте. Поэтому правило простое — на сервере запрос выполняется и сразу материализуется в передаваемый объект, а на клиент уходит уже готовая структура данных.

Способ 1: выгрузка в таблицу значений и возврат через Возврат

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

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

Функция ПолучитьОстатки(Склад)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Остатки.Номенклатура КАК Номенклатура,

| Остатки.КоличествоОстаток КАК Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК Остатки";

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

Возврат Запрос.Выполнить().Выгрузить();

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

&НаКлиенте

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

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

Для Каждого Строка Из ТаблицаОстатков Цикл

Сообщить(Строка(Строка.Номенклатура) + ": " + Строка.Количество);

КонецЦикла;

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

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

Способ 2: массив структур для лёгких данных

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

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

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

Результат = Новый Массив;

Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 100 Ссылка, Наименование ИЗ Справочник.Контрагенты");

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

Пока Выборка.Следующий() Цикл

Результат.Добавить(Новый Структура("Ссылка, Наименование",

Выборка.Ссылка, Выборка.Наименование));

КонецЦикла;

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

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

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

Способ 3: временное хранилище для больших объёмов

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

&НаСервере

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

Таблица = Запрос.Выполнить().Выгрузить();

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

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

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

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

Способ 4: JSON для интеграций и веб-клиента

Если данные с клиента 1С дальше уходят во внешнюю систему, браузерный скрипт или мобильное приложение, удобно вернуть результат запроса в виде строки JSON. Платформа предоставляет объекты ЗаписьJSON и ЧтениеJSON, а также глобальные методы сериализации.

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

Функция ДанныеВJSON()

Запись = Новый ЗаписьJSON;

Запись.УстановитьСтроку();

ЗаписатьJSON(Запись, МассивДанных); // массив структур из запроса

Возврат Запись.Закрыть();

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

Учтите ограничения: ссылки в JSON преобразуются в строковое представление или GUID в зависимости от настроек, даты сериализуются в формат ISO, а специфические типы 1С (тип «Тип», моменты времени) требуют ручной обработки. Для чисто внутренней передачи между клиентом и сервером 1С JSON избыточен — он нужен именно на стыке с внешними системами.

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

Таблица значений

Подходит для умеренных объёмов и дальнейшей обработки на клиенте; при больших объёмах грузит сеть

Массив структур

Лёгкий вариант для списков и подстановок; неудобен для табличного редактирования

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

Оптимально для больших данных и передачи между формами; требует управления временем жизни

JSON

Нужен для интеграций и веб-сценариев; избыточен внутри одной информационной базы

Как проверить, что данные дошли корректно

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

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

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

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

Тип возвращённого значения
Норма

ТаблицаЗначений, Массив или Строка по ожиданию

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

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

Количество строк на клиенте
Норма

Совпадает с количеством в базе по тому же запросу

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

Меньше или ноль — проверьте параметры запроса и отборы

Адрес хранилища
Норма

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

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

Возвращает Неопределено — не передан идентификатор формы

Значения ссылочных полей
Норма

Ссылки открываются и имеют представление

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

Пустые строки — ссылки не сериализовались в JSON корректно

Типичные ошибки и ограничения

Наиболее частая ошибка — попытка вернуть результат запроса или выборку напрямую. Вторая по распространённости — использование директивы &НаКлиенте для процедуры с запросом: на тонком и веб-клиенте объект «Запрос» недоступен, и код просто не скомпилируется. Запросы всегда выполняются в серверном контексте.

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

Типичные ошибки
01
Возврат РезультатЗапроса или Выборки — ошибка сериализации при вызове
02
Запрос в клиентской процедуре — недоступность объекта на тонком клиенте
03
Помещение в хранилище без идентификатора формы — данные удаляются сразу после вызова
04
Передача таблицы на десятки тысяч строк напрямую — зависание интерфейса и рост трафика
05
Присваивание таблицы реквизиту формы напрямую — нужен ЗначениеВРеквизитФормы

Когда стоит привлечь специалиста

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

Итог

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

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

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

Можно ли выполнить запрос прямо на клиенте в управляемом приложении?

Нет. Объект «Запрос» доступен только на сервере. На клиенте можно лишь вызвать серверную функцию и получить от неё готовые данные. В обычном приложении запросы на клиенте возможны, но этот режим считается устаревшим.

Что быстрее: вернуть таблицу значений или адрес временного хранилища?

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

Почему серверная функция возвращает Неопределено, хотя Возврат в коде есть?

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

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

Да. Метод ВыполнитьПакет() возвращает массив результатов; каждый элемент нужно выгрузить отдельно (например, в массив таблиц значений) и вернуть этот массив. Сами результаты пакета, как и одиночный результат, несериализуемы.

Как вернуть данные из фонового задания на клиент?

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

Сериализуются ли картинки и двоичные данные из запроса?

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