Часто возникает задача вынести повторяющиеся действия с пользовательским интерфейсом, например, выбор элемента из справочника, в общий модуль. Чтобы избежать проблем при рефакторинге, полезно выполнять анализ конфигураций и расширений на наличие ошибок в таких модулях. Однако при работе с асинхронными методами, которые не блокируют интерфейс, стандартный возврат значения становится невозможен. Проблема в том, что старые методы, такие как ПоказатьВводЗначения, используют механизм оповещений, который "разрывает" последовательное выполнение кода и требует создания отдельной процедуры-обработчика в модуле формы.
Рассмотрим, как решить эту задачу современным способом, используя актуальные шаблоны стандартов разработки и механизм Асинх/Ждать, чтобы код оставался линейным, читаемым и полностью инкапсулированным в общем модуле.
Ключевая ошибка, с которой столкнулся автор темы, — это попытка использовать оператор Ждать со старой функцией ПоказатьВводЗначения. Этот метод не предназначен для работы с новым синтаксисом асинхронности.
Проанализируем ситуацию:
ПоказатьВводЗначения(), ОткрытьФорму(), Вопрос() не останавливают выполнение кода. Они инициируют действие и сразу же продолжают работу. Чтобы обработать результат (например, выбранное значение или ответ пользователя), нужно передать им объект ОписаниеОповещения. Этот объект указывает, какую процедуру нужно вызвать после завершения асинхронной операции. Это приводит к созданию дополнительных экспортных процедур в модуле формы и усложняет передачу контекста.Асинх/Ждать). В платформе 1С появились специальные асинхронные функции-аналоги, которые возвращают объект Обещание (Promise). Это своего рода "обязательство" предоставить результат в будущем. Оператор Ждать может работать только с такими функциями. Он приостанавливает выполнение текущей процедуры до тех пор, пока "обещание" не будет выполнено, и возвращает его результат. При этом интерфейс программы не блокируется.Таким образом, для решения нашей задачи нужно просто заменить старую функцию на ее новый асинхронный аналог. Вместо ПоказатьВводЗначения следует использовать ВвестиЗначениеАсинх (или, для специфических задач, универсальный ввод значений с расширенными возможностями).
Разберем по шагам, как создать переиспользуемую функцию в общем клиентском модуле, которая будет запрашивать у пользователя значение и возвращать его в место вызова.
Создадим в общем клиентском модуле (например, ОбщиеМеханизмыКлиент) новую функцию. Важно объявить ее с ключевым словом Асинх.
// Общий модуль ОбщиеМеханизмыКлиент
&НаКлиенте
Асинх Экспортная Функция ВыбратьОборудование()
// Можно настроить тип значения, заголовок и другие параметры
ПараметрыВвода = Новый ПараметрыВводаЗначения;
ПараметрыВвода.Заголовок = "Выберите оборудование";
// Используем ВвестиЗначениеАсинх. Этот метод возвращает Обещание.
// Оператор Ждать приостановит выполнение функции до выбора пользователя
// и вернет результат в переменную ВыбранноеЗначение.
ВыбранноеЗначение = Ждать ВвестиЗначениеАсинх(Тип("СправочникСсылка.Оборудование"), ПараметрыВвода);
// Если нужно получить дополнительные данные с сервера, можно сделать еще один асинхронный вызов.
// Для тяжелых операций рекомендуются фоновые задания, отслеживание результата и прогресса.
// Например:
// Если ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
// ДопДанные = Ждать ПолучитьДопДанныеСерверАсинх(ВыбранноеЗначение);
// КонецЕсли;
// Возвращаем результат как в обычной синхронной функции
Возврат ВыбранноеЗначение;
КонецФункции
Что здесь происходит? Функция ВвестиЗначениеАсинх открывает стандартное окно для выбора значения. Оператор Ждать "ловит" результат этого выбора (или Неопределено, если пользователь нажал "Отмена") и записывает его в переменную. После этого функция возвращает это значение с помощью оператора Возврат.
Теперь в любой форме, где нужно выбрать оборудование, мы можем вызвать нашу функцию из общего модуля. Обработчик команды (например, нажатия кнопки) также должен быть объявлен как асинхронный с помощью ключевого слова Асинх.
// Модуль формы
&НаКлиенте
Асинх Процедура ПриНажатииКнопкиВыбора(Команда)
// Вызываем нашу функцию и дожидаемся результата.
// Весь сложный код инкапсулирован в общем модуле.
Результат = Ждать ОбщиеМеханизмыКлиент.ВыбратьОборудование();
// Далее работаем с результатом, как будто это был обычный синхронный вызов
Если ЗначениеЗаполнено(Результат) Тогда
// Присваиваем результат реквизиту формы
Объект.Оборудование = Результат;
Сообщить("Выбрано оборудование: " + Результат);
Иначе
Сообщить("Выбор был отменен.");
КонецЕсли;
КонецПроцедуры
Как видите, код в форме получился очень простым и лаконичным. Мы вызываем одну функцию и сразу получаем результат. Вся логика по открытию окна выбора и ожиданию скрыта в общем модуле.
ОткрытьФормуАсинхМетод ВвестиЗначениеАсинх отлично подходит для простого выбора значения. Но что если нам нужна сложная форма выбора с таблицами, фильтрами, и несколькими кнопками? Если вы конструируете такие формы динамически, вам может пригодиться программное изменение форм, но для открытия используется мощный инструмент — ОткрытьФормуАсинх.
Принцип работы очень похож:
Справочник.Оборудование.Форма.ФормаВыбора), в обработчике команды "Выбрать" необходимо вызвать метод ЗакрытьСРезультатом(ВыбранноеЗначение). Этот метод закроет форму и "вернет" указанное значение в качестве результата.ОткрытьФормуАсинх и дожидаемся ее закрытия с помощью Ждать.Посмотрим на пример вызова сложной формы выбора:
&НаКлиенте
Асинх Процедура ВыбратьИзСложнойФормы(Команда)
// Открываем форму выбора и ждем, пока она не будет закрыта
// методом ЗакрытьСРезультатом().
РезультатВыбора = Ждать ОткрытьФормуАсинх("Справочник.Оборудование.Форма.ФормаВыбораСФильтрами");
Если РезультатВыбора <> Неопределено Тогда
Объект.Оборудование = РезультатВыбора;
Сообщить("Выбор из сложной формы завершен успешно!");
КонецЕсли;
КонецПроцедуры
Этот подход позволяет создавать гибкие и переиспользуемые диалоги, сохраняя при этом чистоту и читаемость основного кода.
В заключение: использование механизма Асинх/Ждать и новых асинхронных функций платформы (ВвестиЗначениеАсинх, ОткрытьФормуАсинх, ВопросАсинх и др.) — это современный стандарт для работы с интерактивными операциями в 1С. Он позволяет избавиться от "ада обратных вызовов" (callback hell) и писать простой, последовательный код.