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

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

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

Архитектурные особенности взаимодействия клиент-сервер

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

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

Однако данные, полученные в результате выполнения запроса, необходимо как-то доставить пользователю. Механизм сериализации данных при передаче через границу контекста требует времени и ресурсов процессора. Если передать миллион строк таблицы значений, интерфейс зависнет на время распаковки этих данных. Именно поэтому важно использовать специализированные типы, такие как ТаблицаЗначений или ДеревоЗначений, которые оптимизированы для такой передачи.

⚠️ Внимание: Никогда не пытайтесь передавать через границу клиент-сервер объекты, содержащие ссылки на серверные ресурсы, такие как потоки (Поток) или соединения с внешними базами. Они не сериализуются и вызовут ошибку выполнения.

💡

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

Классический метод: ВызватьСерверныйПроцедура

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

Для реализации этого подхода необходимо создать процедуру на сервере, помеченную директивой &НаСервере. В параметрах этой процедуры обязательно должен быть хотя бы один аргумент, передаваемый по ссылке (с ключевым словом Знач или без него, но с изменением значения), который будет служить контейнером для возвращаемых данных. Обычно в эту переменную записывается результат метода Запрос.Выполнить().Выгрузить().

&НаСервере

Процедура ПолучитьДанныеНаСервере(Знач ПараметрыОтбора, РезультатЗапроса)

ТекстЗапроса = "ВЫБРАТЬ Номенклатура.Наименование, Номенклатура.Артикул

|ИЗ Справочник.Номенклатура КАК Номенклатура

|ГДЕ Номенклатура.ВидНоменклатуры = &Вид";

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

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

Запрос.УстановитьПараметр("Вид", ПараметрыОтбора);

// Выгрузка в таблицу значений для оптимизации передачи

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

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

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

  • 🚀 Этот метод идеально подходит для форм, где данные нужны сразу при открытии.
  • 🛡️ Гарантирует типобезопасность и контроль за передаваемыми структурами.
  • 🔄 Позволяет легко передавать параметры отбора из элементов формы.

☑️ Алгоритм получения данных

Выполнено: 0 / 4

Работа с выборками и курсорами на сервере

Иногда прямой выгрузки всей таблицы значений недостаточно, особенно если требуется сложная пост-обработка каждой строки результата перед отправкой клиенту. В таких случаях разработчики используют объект Выборка. Это позволяет проходить по результатам запроса построчно, применяя логику, которую трудно или невозможно реализовать средствами языка запросов.

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

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

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

⚠️ Внимание: Избегайте выполнения дополнительных запросов внутри цикла обхода выборки. Это приводит к проблеме N+1 запроса и может положить сервер базы данных под нагрузкой.

Использование Компоновки Данных (СКД) для отчетов

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

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

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

Метод передачи Тип возвращаемых данных Лучшее применение Сложность реализации
ВызватьСерверныйПроцедура ТаблицаЗначений Заполнение табличных частей, списков Низкая
СКД (Компоновка) РезультатКомпоновкиДанных Аналитические отчеты, печати Средняя
HTTP-сервис JSON / XML строка Внешние системы, веб-клиенты Высокая
Потоки данных Двоичные данные Выгрузка файлов, больших объемов Высокая
Оптимизация СКД

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

Современные подходы: HTTP-сервисы и JSON

В современных распределенных системах, где 1С выступает в роли бэкенда для мобильных приложений или веб-порталов, классические методы могут быть избыточны или неудобны. Здесь на сцену выходят HTTP-сервисы. Они позволяютExpose (открыть) функционал 1С в виде стандартных веб-методов, принимающих и возвращающих данные в формате JSON.

Чтобы вернуть результат запроса через HTTP-сервис, необходимо создать обработчик HTTP-сервиса в конфигурации. Внутри метода обработчика (например, ПолучитьНоменклатуру) выполняется запрос, результат выгружается в таблицу значений, а затем эта таблица конвертируется в JSON-строку с помощью объекта ЗаписьJSON и специализированных функций записи структуры.

Функция ПолучитьДанныеJSON()

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

Запрос.Текст = "ВЫБРАТЬ..";

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

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

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

ЗаписатьJSON(Запись, ТаблицаДанных);

Возврат Запись.ЗакрытьИПолучитьСтроку();

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

Такой подход делает систему агностичной к типу клиента. Данные в формате JSON могут быть потреблены любым языком программирования — JavaScript, Python, C#. Это открывает возможности для создания богатых клиентских интерфейсов, не зависящих от платформы 1С, при этом вся бизнес-логика и безопасность данных остаются на сервере 1С.

📊 Какой метод передачи данных вы используете чаще всего?
ВызватьСерверныйПроцедура
СКД (Отчеты)
HTTP-сервисы (JSON)
Файловый обмен

Оптимизация передачи больших объемов данных

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

В таких случаях следует применять стратегию «ленивой загрузки» или разбивку на пакеты. Вместо того чтобы возвращать весь результат запроса одним массивом, серверная процедура может принимать параметр «НомерСтраницы» и «РазмерСтраницы». Запрос на сервере выполняется с использованием операторов ПЕРВЫЕ N и ПРОПУСТИТЬ M.

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

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

⚠️ Внимание: При работе с большими данными в веб-клиенте учитывайте ограничения браузера на объем памяти. Передача слишком больших JSON-объектов или ТаблицЗначений может привести к падению вкладки браузера.

💡

Главное правило оптимизации: передавайте на клиент только те данные, которые пользователь видит на экране прямо сейчас, а не весь массив доступной информации.

Обработка ошибок и исключительных ситуаций

При организации обмена данными между клиентом и сервером необходимо предусматривать сценарии сбоев. Сеть может оборваться, сервер может быть перегружен, а в базе данных могут возникнуть блокировки. Если серверная процедура, возвращающая данные, завершится ошибкой, клиентское приложение должно корректно обработать эту ситуацию, а не просто «упасть».

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

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

Логирование является важным инструментом отладки. В сложных случаях, когда данные «теряются» по пути, добавляйте записи в журнал регистрации на ключевых этапах: перед выполнением запроса, после выгрузки данных и перед возвратом управления клиенту. Это поможет быстро локализовать проблему.

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

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

В чем разница между ТаблицейЗначений и ДеревомЗначений при передаче?

ТаблицаЗначений представляет собой плоский список записей. ДеревоЗначений поддерживает иерархическую структуру (вложенные строки). При передаче на клиент ДеревоЗначений занимает чуть больше ресурсов из-за структуры узлов, но позволяет сразу отображать данные в виде иерархического списка без дополнительной обработки на клиенте.

Как передать результат запроса в печатную форму?

Для печати результат запроса обычно выгружается в макет (ТабличныйДокумент или ОбластьМакета). Серверная процедура формирует макет, заполняет его данными из запроса и возвращает объект макета клиенту, где он отправляется на устройство вывода.

Почему ВызватьСерверныйПроцедура блокирует интерфейс?

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

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

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