Как правильно передать массив с клиента на сервер в 1С 8.3?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Понимание клиент-серверного взаимодействия

Прежде чем мы перейдем к коду, давайте проанализируем, что происходит в момент вызова серверного метода. Когда мы вызываем процедуру или функцию с директивой &НаСервере, платформа выполняет маршалинг (сериализацию) параметров. Это означает, что данные упаковываются в специальный формат, передаются по сети и распаковываются на стороне сервера. Для успешной передачи объект должен поддерживать сериализацию. Для лучшего понимания работы директив компиляции можно использовать руководство по управлению контекстом выполнения в управляемых формах.

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

Простой пример передачи массива

Рассмотрим стандартную ситуацию: на стороне клиента мы формируем список идентификаторов (например, кодов товаров) и хотим передать их на сервер для выполнения запроса или обработки. Проанализируем пример кода, реализующий эту задачу.


&НаКлиенте
Процедура ОбработатьДанныеНаСервере()
    
    // Создаем массив на клиенте
    СписокКодов = Новый Массив;
    СписокКодов.Добавить("00001");
    СписокКодов.Добавить("00005");
    СписокКодов.Добавить("00012");
    
    // Передаем массив в серверную функцию
    РезультатОбработки = ВыполнитьДействиеНаСервере(СписокКодов);
    
    // Выводим результат пользователю
    Сообщить("Обработано элементов: " + РезультатОбработки);
    
КонецПроцедуры

&НаСервере
Функция ВыполнитьДействиеНаСервере(ВходящийМассив)
    
    // На сервере мы можем работать с массивом как обычно
    Количество = ВходящийМассив.Количество();
    
    Для Каждого Элемент Из ВходящийМассив Цикл
        // Здесь может быть логика поиска в БД или изменения данных
        ЗаписьЖурналаРегистрации("Обработка кода: " + Элемент);
    КонецЦикла;
    
    Возврат Количество;
    
КонецФункции

В данном примере мы видим, что СписокКодов передается как обычный параметр. Платформа берет на себя всю работу по преобразованию данных для передачи по протоколу HTTP или TCP (в зависимости от типа подключения).

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

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

  1. Объекты базы данных напрямую: Нельзя положить в массив СправочникОбъект или ДокументОбъект и передать его. Вместо объектов следует использовать СправочникСсылка или ДокументСсылка.
  2. Таблицы значений: Объект ТаблицаЗначений не существует на тонком клиенте. Если вы попытаетесь передать массив, содержащий таблицу значений, с сервера на клиент, система выдаст ошибку. Для обмена табличными данными следует использовать массив структур или ДанныеФормыКоллекция.
  3. Ком-объекты: Специфические объекты операционной системы также не подлежат передаче через границу контекстов.

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


&НаСервере
Функция ПолучитьДанныеДляКлиента()
    
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Наименование");
    ТЗ.Колонки.Добавить("Цена");
    
    // Заполняем ТЗ данными...
    
    // Конвертируем ТЗ в массив структур для передачи на клиент
    МассивРезультат = Новый Массив;
    Для Каждого СтрокаТЗ Из ТЗ Цикл
        НоваяСтруктура = Новый Структура("Наименование, Цена", СтрокаТЗ.Наименование, СтрокаТЗ.Цена);
        МассивРезультат.Добавить(НоваяСтруктура);
    КонецЦикла;
    
    Возврат МассивРезультат;
    
КонецФункции

Передача массива по ссылке и по значению

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

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

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

Рассмотрим ситуацию, когда объем передаваемых данных велик. Каждый вызов сервера — это "дорогостоящая" операция. Проанализируем рекомендации по оптимизации:

Посмотрим на пример использования временного хранилища для передачи данных, если мы хотим передать массив и работать с ним асинхронно или в разных вызовах.


&НаКлиенте
Процедура ПередатьЧерезХранилище()
    
    МассивДанных = Новый Массив;
    // ... заполнение массива ...
    
    АдресХранилища = ПоместитьВоВременноеХранилище(МассивДанных, УникальныйИдентификатор);
    
    ОбработатьНаСервереПоАдресу(АдресХранилища);
    
КонецПроцедуры

&НаСервере
Процедура ОбработатьНаСервереПоАдресу(Адрес)
    
    // Извлекаем массив из хранилища
    МассивНаСервере = ПолучитьИзВременногоХранилища(Адрес);
    
    Если ТипЗнч(МассивНаСервере) = Тип("Массив") Тогда
        // Обработка...
    КонецЕсли;
    
КонецПроцедуры

Заключение

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

Помните, что правильное проектирование взаимодействия контекстов — это залог высокой производительности системы. Всегда старайтесь выполнять максимум подготовки данных на той стороне, где они находятся, чтобы минимизировать нагрузку на сеть при вызовах &НаСервере.

← На главную