Почему при вызове сервера без контекста очищается поле ввода и как это исправить?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто встречается загадочная ситуация: программист использует директиву &НаСервереБезКонтекста, чтобы минимизировать нагрузку и избежать передачи контекста формы, однако форма ведет себя так, будто выполняется полноценный контекстный вызов. Самый неприятный симптом — внезапное исчезновение текста, который пользователь в данный момент вводит в поле (очистка текста редактирования). Разберем по шагам, почему это происходит и как устранить этого «барабашку».

Суть проблемы: когда «без контекста» не значит «без синхронизации»

Рассмотрим стандартную ситуацию. В форме настроен обработчик ожидания, который раз в несколько секунд обращается к серверу для обновления каких-либо данных (например, списка последних файлов или уведомлений). Программист справедливо использует &НаСервереБезКонтекста, чтобы не гонять данные всей формы туда-обратно. Однако на некоторых рабочих местах пользователи начинают жаловаться: «Я пишу текст в поле, и вдруг всё пропадает!».

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

Роль ключевого слова Знач в серверных вызовах

Выясним, как передача параметров влияет на поведение формы. В языке 1С параметры в процедуры могут передаваться двумя способами: по значению (копия) и по ссылке (указатель на объект). Рассмотрим пример кода, который вызывает проблему:


&НаКлиенте
Процедура ОбработчикОжидания()
    // СписокФайлов — это реквизит формы (СписокЗначений)
    ПолучитьДанныеНаСервере(СписокФайлов); 
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПолучитьДанныеНаСервере(ПараметрСписок)
    // Изменение ПараметрСписок здесь приведет к обновлению реквизита на форме
    ПараметрСписок.Добавить("Новый элемент");
КонецПроцедуры

В данном случае ПараметрСписок передается по ссылке. Несмотря на директиву &НаСервереБезКонтекста, платформа видит, что вы передали реквизит формы, и после выполнения серверного кода обновляет его на клиенте. Это обновление и «срубает» фокус или текст в активном поле ввода.

Решение №1: Используйте ключевое слово Знач. Если вам нужно передать данные на сервер только для чтения или вы планируете вернуть результат иным способом (например, через возвращаемое значение функции), всегда указывайте Знач.


&НаСервереБезКонтекста
Процедура ПолучитьДанныеНаСервере(Знач МассивДанных, РезультатМассив)
    // Работа с копией данных
КонецПроцедуры

Проблема типов данных и «демоническое обновление»

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

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

Решение №2: Очистка кэша. Если проблема воспроизводится локально на конкретных машинах, необходимо:

  1. Очистить локальный кэш пользователя (удалить базу из списка и добавить заново или почистить папку %AppData%\1C\1Cv8).
  2. В случае клиент-серверного варианта — перезапустить службу сервера 1С и очистить серверный кэш (папка snccntx в каталоге данных сервера).

Правильная архитектура обновления данных в фоне

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

  1. Не передавайте реквизиты формы напрямую. Вместо передачи СписокЗначений или ТаблицаЗначений (которые являются реквизитами), создайте на клиенте новый массив или структуру, скопируйте туда нужные данные и передайте этот «независимый» объект на сервер.
  2. Возвращайте данные, а не меняйте их в процедуре. Лучше использовать функцию, которая возвращает результат, и уже на клиенте программно обновлять реквизиты формы.
  3. Проверяйте активность элемента. Если вы обновляете данные, которые выведены на форму, проверьте, не находится ли пользователь в процессе редактирования этого конкретного списка или поля.

Рассмотрим пример правильной реализации:


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

    // Переподключаем обработчик
    ПодключитьОбработчикОжидания("ПолучитьСписокПоследнихФайлов", 60, Истина);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСписокНаСервере(Знач ВходнойМассив)
    Результат = Новый Массив;
    // Логика обработки данных...
    Возврат Результат;
КонецФункции

Подведем итоги

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

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

← На главную