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