В практике разработки на платформе 1С:Предприятие 8.3 часто встречается загадочная ситуация: программист использует директиву &НаСервереБезКонтекста, чтобы минимизировать нагрузку и избежать передачи контекста формы, однако форма ведет себя так, будто выполняется полноценный контекстный вызов. Самый неприятный симптом — внезапное исчезновение текста, который пользователь в данный момент вводит в поле (очистка текста редактирования). Разберем по шагам, почему это происходит и как устранить этого «барабашку».
Рассмотрим стандартную ситуацию. В форме настроен обработчик ожидания, который раз в несколько секунд обращается к серверу для обновления каких-либо данных (например, списка последних файлов или уведомлений). Программист справедливо использует &НаСервереБезКонтекста, чтобы не гонять данные всей формы туда-обратно. Однако на некоторых рабочих местах пользователи начинают жаловаться: «Я пишу текст в поле, и вдруг всё пропадает!».
Проанализируем причину. Платформа 1С устроена так, что даже во внеконтекстном вызове существует механизм синхронизации данных, если в параметры серверной процедуры передаются объекты, напрямую связанные с данными формы. Если параметр передается по ссылке (без ключевого слова Знач), 1С по завершении процедуры пытается вернуть измененное состояние объекта на клиент. Для платформы это сигнал о том, что данные формы потенциально изменились, и она инициирует обновление связанных элементов управления. Это обновление «перерисовывает» поле ввода, обнуляя незафиксированный ТекстРедактирования.
Выясним, как передача параметров влияет на поведение формы. В языке 1С параметры в процедуры могут передаваться двумя способами: по значению (копия) и по ссылке (указатель на объект). Рассмотрим пример кода, который вызывает проблему:
&НаКлиенте
Процедура ОбработчикОжидания()
// СписокФайлов — это реквизит формы (СписокЗначений)
ПолучитьДанныеНаСервере(СписокФайлов);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПолучитьДанныеНаСервере(ПараметрСписок)
// Изменение ПараметрСписок здесь приведет к обновлению реквизита на форме
ПараметрСписок.Добавить("Новый элемент");
КонецПроцедуры
В данном случае ПараметрСписок передается по ссылке. Несмотря на директиву &НаСервереБезКонтекста, платформа видит, что вы передали реквизит формы, и после выполнения серверного кода обновляет его на клиенте. Это обновление и «срубает» фокус или текст в активном поле ввода.
Решение №1: Используйте ключевое слово Знач. Если вам нужно передать данные на сервер только для чтения или вы планируете вернуть результат иным способом (например, через возвращаемое значение функции), всегда указывайте Знач.
&НаСервереБезКонтекста
Процедура ПолучитьДанныеНаСервере(Знач МассивДанных, РезультатМассив)
// Работа с копией данных
КонецПроцедуры
Иногда проблема проявляется выборочно: у одних пользователей всё работает штатно, у других — форма «глючит». Проанализируем ситуацию с кэшем метаданных. Одной из причин может быть так называемое «демоническое обновление» (динамическое обновление конфигурации без выгона пользователей). В этом режиме кэш на сервере и клиенте может рассинхронизироваться.
Например, в СписокЗначений (реквизит формы) на одной машине тип значения определен как Строка, а на другой, из-за сбоя кэша, он может внезапно интерпретироваться как Дата или Произвольный. При попытке синхронизации данных платформа находит несоответствие типов и инициирует принудительное полное обновление состояния формы, что приводит к сбросу текущих действий пользователя.
Решение №2: Очистка кэша. Если проблема воспроизводится локально на конкретных машинах, необходимо:
%AppData%\1C\1Cv8).snccntx в каталоге данных сервера).Чтобы избежать неявных контекстных вызовов и «барабашек» с интерфейсом, рекомендуется придерживаться следующей стратегии при работе с обработчиками ожидания:
СписокЗначений или ТаблицаЗначений (которые являются реквизитами), создайте на клиенте новый массив или структуру, скопируйте туда нужные данные и передайте этот «независимый» объект на сервер.Рассмотрим пример правильной реализации:
&НаКлиенте
Процедура ПолучитьСписокПоследнихФайлов()
МассивДляСервера = Новый Массив; // Создаем независимый объект
// Заполняем массив...
// Вызываем сервер и получаем результат в новый локальный массив
РезультатССервера = ПолучитьСписокНаСервере(МассивДляСервера);
// Обновляем реквизит формы СписокФайлов только на клиенте
Для Каждого СтрокаРезультата Из РезультатССервера Цикл
Если СписокФайлов.НайтиПоЗначению(СтрокаРезультата.Путь) = Неопределено Тогда
СписокФайлов.Добавить(СтрокаРезультата.Путь, СтрокаРезультата.Имя);
КонецЕсли;
КонецЦикла;
// Переподключаем обработчик
ПодключитьОбработчикОжидания("ПолучитьСписокПоследнихФайлов", 60, Истина);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСписокНаСервере(Знач ВходнойМассив)
Результат = Новый Массив;
// Логика обработки данных...
Возврат Результат;
КонецФункции
Мы проанализировали ситуацию, когда внеконтекстный вызов сервера мешает работе пользователя. Основная причина — неявная синхронизация реквизитов формы, передаваемых в параметры серверной процедуры по ссылке. Платформа воспринимает это как изменение данных формы, что заставляет элементы управления сбрасывать состояние «редактирования текста».
Чтобы ваш интерфейс работал плавно и предсказуемо, всегда используйте ключевое слово Знач для входящих параметров и старайтесь выполнять обновление данных реквизитов формы исключительно на стороне клиента, получая с сервера «чистые» данные (массивы, структуры, таблицы значений), не связанные с контекстом конкретной формы.