Разработка и Конфигурация · 11 мин
Чем заменить Предупреждение() в 1С: практическое руководство
Почему метод Предупреждение() устарел в 1С и чем его заменить: ПоказатьПредупреждение, ПоказатьВопрос, СообщениеПользователю. Примеры кода и типичные ошибки.
Метод Предупреждение() пришёл в управляемые формы из обычного приложения и давно считается устаревшим. В тонком и веб-клиенте он работает через модальные окна, которые блокируют интерфейс, а в ряде режимов вообще недоступен. Платформа 1С предлагает взамен асинхронные методы с описанием оповещения — ПоказатьПредупреждение(), ПоказатьВопрос(), а для служебных сообщений — объект СообщениеПользователю.
Проблема модальных окон не только в эстетике. В веб-клиенте браузеры блокируют синхронные диалоги, а режим использования модальности в типовых конфигурациях обычно установлен в «Не использовать». При такой настройке вызов Предупреждение() либо вызывает ошибку, либо игнорируется — и пользователь просто не увидит сообщение. Поэтому замена нужна не «для красоты», а для корректной работы кода.
Ниже разобраны все рабочие альтернативы: когда достаточно простого сообщения в панели, когда нужен асинхронный диалог с обработкой ответа, как переписать старый код без потери логики и какие ошибки встречаются чаще всего при такой миграции.
Почему Предупреждение() больше нельзя использовать
Метод Предупреждение() — синхронный: выполнение кода останавливается, пока пользователь не закроет окно. Такая модель несовместима с веб-клиентом, где скрипт в браузере не может «замереть» в ожидании. Поэтому платформа ввела свойство конфигурации «Режим использования модальности» и набор асинхронных аналогов.
Проверить текущий режим можно в конфигураторе: свойства корня конфигурации, параметр «Режим использования модальности». Если там стоит «Не использовать» — любой вызов Предупреждение(), Вопрос() или ОткрытьФормуМодально() приведёт к ошибке выполнения. В типовых конфигурациях именно этот режим является стандартом.
Вторая причина — проверка расширений и публикация решений. Многие аудиторские проверки и стандарты разработки прямо запрещают модальные вызовы, поэтому старый код придётся переписывать в любом случае.
Замена без ответа пользователя: СообщениеПользователю
Самый частый сценарий использования Предупреждение() — просто сообщить пользователю о проблеме: «Не заполнено поле», «Документ не проведён». Для этого модальное окно избыточно: достаточно объекта СообщениеПользователю, который выводит текст в панель сообщений, не прерывая работу.
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = НСтр("ru = 'Не заполнен склад отгрузки'");
Сообщение.Поле = "Склад";
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();
Преимущество подхода — привязка к полю формы: пользователь кликает по сообщению и сразу переходит к незаполненному реквизиту. Это удобнее, чем окно, которое нужно закрыть, а потом вспоминать, что именно было не так.
Выбирайте СообщениеПользователю в проверках заполнения, обработчиках записи и проведения — там, где код должен продолжить работу или где сообщений может быть несколько сразу. Модальное окно показывает одно сообщение за раз, панель — список целиком.
Прямая замена: ПоказатьПредупреждение с оповещением
Если всё же нужен отдельный диалог — например, важное уведомление, которое пользователь обязан увидеть, — используется ПоказатьПредупреждение(). Метод асинхронный: код после вызова не ждёт закрытия окна, а продолжение логики переносится в процедуру обработки оповещения.
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияПредупреждения", ЭтотОбъект);
ПоказатьПредупреждение(ОписаниеОповещения,
НСтр("ru = 'Документ будет перепроведён'"),
10,
НСтр("ru = 'Внимание'"));
&НаКлиенте
Процедура ПослеЗакрытияПредупреждения(ДополнительныеПараметры) Экспорт
// Продолжение логики после закрытия окна
КонецПроцедуры
Параметры метода: описание оповещения (можно передать Неопределено, если реакция не нужна), текст, таймаут в секундах (0 — без ограничения) и заголовок. Процедура обработчика должна быть экспортной и находиться в клиентском контексте.
Ключевое отличие от старого метода — структура кода. Раньше всё, что шло после Предупреждение(), выполнялось после закрытия окна. Теперь это «продолжение» нужно физически перенести в процедуру оповещения, иначе оно выполнится сразу, до реакции пользователя.
- 1Найдите вызов Предупреждение() и определите, нужна ли реакция на закрытие окна
- 2Если реакция не нужна — замените на СообщениеПользователю или ПоказатьПредупреждение без оповещения
- 3Если нужна — создайте экспортную клиентскую процедуру-продолжение и перенесите в неё код после старого вызова
- 4Сформируйте ОписаниеОповещения с именем этой процедуры и передайте его первым параметром
- 5Проверьте работу в тонком и веб-клиенте: окно должно появляться без ошибок модальности
Диалоги с выбором: ПоказатьВопрос вместо Вопрос()
Если старый код использовал Вопрос() или Предупреждение() как способ подтверждения («Продолжить? Да/Нет»), правильная замена — ПоказатьВопрос(). Метод показывает диалог с настраиваемыми кнопками и возвращает результат в процедуру оповещения.
Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
ПоказатьВопрос(Оповещение,
НСтр("ru = 'Очистить табличную часть?'"),
РежимДиалогаВопрос.ДаНет,
20,
КодВозвратаДиалога.Нет);
&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
Объект.Товары.Очистить();
КонецЕсли;
КонецПроцедуры
Обратите внимание на обработку таймаута: если пользователь не ответил за отведённое время, в обработчик приходит значение КодВозвратаДиалога.Таймаут. Его нужно обрабатывать явно, иначе при истечении времени может выполниться непредусмотренная ветка логики.
Дополнительные данные в обработчик передаются третьим параметром конструктора ОписаниеОповещения — например, ссылку на документ или структуру с контекстом. Это заменяет переменные, которые раньше были доступны «ниже по коду».
Сравнение вариантов замены
Для служебных сообщений и ошибок заполнения. Не прерывает работу, привязывается к полю. Не подходит, если нужна обязательная реакция пользователя.
Для важных уведомлений, которые пользователь должен подтвердить. Требует переноса продолжения логики в процедуру оповещения.
Для подтверждений и выбора (Да/Нет, ОК/Отмена). Возвращает результат в обработчик, нужна обработка таймаута.
Если старый код через диалог запрашивал данные. Асинхронные аналоги ввода значений.
Типичные ошибки при замене
Самая распространённая ошибка — оставить код после вызова ПоказатьПредупреждение() в той же процедуре и ожидать, что он выполнится после закрытия окна. Асинхронный метод возвращает управление немедленно, поэтому весь «хвост» логики должен жить в процедуре оповещения.
Вторая ошибка — неэкспортная процедура обработчика или обработчик в серверном контексте. Платформа не сможет вызвать такую процедуру, и оповещение завершится ошибкой. Процедура должна быть объявлена с ключевым словом Экспорт в клиентском модуле или клиентской части модуля формы.
Третья группа ошибок — потеря контекста. В старом коде после Предупреждение() были доступны локальные переменные; в асинхронном варианте их нужно передать через ДополнительныеПараметры описания оповещения, обычно в виде структуры.
Как проверить результат и найти оставшиеся вызовы
После замены полезно пройтись поиском по конфигурации: в конфигураторе через «Правка → Глобальный поиск» найдите строки Предупреждение(, Вопрос( и ОткрытьФормуМодально. Убедитесь, что оставшихся вызовов нет или они завернуты в явную проверку режима модальности для совместимости.
Функциональную проверку выполняйте в двух клиентах: тонком и веб-клиенте. Признаки корректной работы — окно появляется без ошибок, после закрытия выполняется именно процедура-продолжение, при таймауте срабатывает предусмотренная ветка. Если сообщение выводится через СообщениеПользователю, проверьте, что клик по нему активирует нужное поле формы.
Как проверить результат
Диалог открывается, ошибок модальности нет
Ошибка выполнения или окно не появляется
Код выполняется в процедуре оповещения после закрытия диалога
Код выполнился сразу, до реакции пользователя
При молчании срабатывает ветка по умолчанию
Таймаут приводит к непредусмотренному действию
Клик по сообщению активирует поле формы
Сообщение без привязки, пользователь ищет поле вручную
Часто задаваемые вопросы
Можно ли оставить Предупреждение(), если конфигурация работает только в толстом клиенте?
Технически — да, если режим использования модальности это разрешает. Но это создаёт технический долг: при переходе на тонкий или веб-клиент весь такой код придётся переписывать срочно. Разумнее заменить вызовы планово.
Чем ПоказатьПредупреждение отличается от Сообщить()?
ПоказатьПредупреждение выводит отдельный диалог, который пользователь должен закрыть, и позволяет выполнить код после закрытия. Сообщить() просто добавляет текст в панель сообщений, не требуя реакции. Для ошибок заполнения предпочтителен второй вариант, для критичных уведомлений — первый.
Как передать данные в процедуру обработки оповещения?
Третьим параметром конструктора ОписаниеОповещения передайте произвольное значение — обычно структуру. В процедуре-обработчике оно придёт как параметр ДополнительныеПараметры.
Почему обработчик оповещения не вызывается, хотя окно показывается?
Чаще всего процедура не объявлена с ключевым словом Экспорт, находится в серверном контексте или имя в ОписанииОповещения указано с ошибкой. Проверьте также, что процедура расположена в том же модуле, который указан вторым параметром описания оповещения.
Нужно ли обрабатывать таймаут у ПоказатьПредупреждение?
Если таймаут задан и передано оповещение, обработчик вызовется и при истечении времени — без дополнительных признаков. Для ПоказатьВопрос таймаут приходит как отдельное значение КодВозвратаДиалога.Таймаут, и его нужно обрабатывать явно.
Что делать со вложенными диалогами — вопрос после вопроса?
Каждый следующий диалог вызывается из процедуры оповещения предыдущего. Получается цепочка обработчиков. При глубокой вложенности имеет смысл пересмотреть логику: возможно, часть вопросов заменяется одной формой с настройками.
Что важно запомнить
Предупреждение() заменяется на СообщениеПользователю для служебных сообщений, на ПоказатьПредупреждение для важных уведомлений и на ПоказатьВопрос для подтверждений. Все асинхронные методы требуют переноса продолжения логики в экспортную клиентскую процедуру оповещения и явной обработки таймаута.