Методические рекомендации по конфигурированию
29.05.2013
В статье будут рассмотрены причины отказа от дальнейшей поддержки модальных окон в платформе «1С:Предприятие» и типовые сценарии перевода имеющегося функционала на новую модель.
Одним из основных векторов развития платформы «1С:Предприятие» является возможность ее успешного использования в среде Интернет.
Эта среда имеет ряд ограничений, которые отсутствуют в среде настольных приложений:
Приложения, предназначенные для работы через Интернет, должны быть построены с учетом этих ограничений, поэтому их модель отличается от настольных приложений.
Все интернет-приложения создаются с использованием асинхронной (событийно-управляемой) модели управления логикой, в отличие от принятой в настольных приложениях синхронной (последовательной) модели.
Изначально платформа «1С:Предприятие» создавалась для построения настольных бизнес-приложений, использующих синхронную модель. Однако, с развитием SaaS-решений потребовался постепенный переход на асинхронную логику.
Модальные окна являются элементом синхронной модели. Они блокируют исполнение логики приложения, позволяя выполнять ее участки последовательно, друг за другом, в зависимости от результата, полученного от пользователя.
Такие окна не входят в стандарт веб-разработки, поэтому не поддерживаются всеми браузерами, при помощи которых пользователь получает доступ к приложениям «1С».
Для разработки качественных веб-приложений требуются асинхронные средства обеспечения взаимодействия с пользователем.
Такие средства были добавлены в платформу «1С:Предприятие» в версии 8.3.3.
Далее в статье будут использоваться следующие термины:
В синхронной модели код, зависящий от выбора пользователя, выполняется последовательно.
В асинхронной модели мы можем получить результат только обрабатывая события, которые возникают, когда пользователь делает свой выбор. При этом на время ожидания выбора код приложения не останавливается и оно продолжает работать.
Таким образом, получается, что такой код разбивается на две процедуры:
Для реализации асинхронной модели в первую очередь требуется возможность описания процедур-обработчиков оповещений, которые будут вызваны системой при завершении выбора пользователя.
Для этого в платформу был добавлен новый тип объектов - ОписаниеОповещения.
Этот объект имеет конструктор со следующими параметрами:
Для получения значения модуля у вышеперечисленных объектов добавлено общее свойство ЭтотОбъект.
При вызове указанной процедуры системой ей через параметры передается результат выбора пользователя и значение ДополнительныеПараметры. В некоторых случаях результат выбора может отсутствовать (метод ПоказатьПредупреждение()) или передаваться несколькими параметрами (метод НачатьПомещениеФайла()).
Для перехода на асинхронную модель в платформу были добавлены методы, аналогичные модальным методам, но, в отличие от них, не блокирующие поток исполнения. Эти методы уже не являются элементами синхронной логики, поэтому могут беспрепятственно использоваться при разработке веб-приложений.
Группа этих методов отличается следующим:
Также были добавлены возможности работы с управляемыми формами в асинхронной модели. Однако, для них не создавалось новых методов, а были доработаны уже имеющиеся средства:
Дополнительно реализован новый метод глобального контекста ВыполнитьОбработкуОповещения(), который позволяет вручную осуществить вызов процедуры-обработчика. Это позволяет реализовать общую процедуру, выполняющую опрос пользователя, которая вызывается из разных мест.
Следует отметить, что поначалу асинхронная модель может показаться сложнее привычной синхронной. На самом деле, понимая основные различия этих моделей, разработка асинхронных приложений становится не многим труднее.
Это подтверждается тем фактом, что все современные веб-приложения построены именно с использованием асинхронной модели и их количество постоянно растет.
Наиболее частым сценарием является получение информации от пользователя во время исполнения какой-либо команды.
Допустим, существует следующий код, написанный в рамках синхронной модели:
&НаКлиенте Процедура ДобавитьХарактеристику(Команда) //Выберем вид характеристики ВидХарактеристики = ОткрытьФормуМодально("ПланВидовХарактеристик.ВидыХарактеристик.ФормаВыбора"); Если ВидХарактеристики = Неопределено Тогда Возврат; КонецЕсли; //Проверим наличие Если ОписаниеХарактеристик.НайтиСтроки( Новый Структура("ВидХарактеристики", ВидХарактеристики)).Количество() > 0 Тогда Предупреждение(НСтр("ru = 'Характеристика уже существует!'", "ru")); Возврат; КонецЕсли; //Добавим вид характеристики на форму ДобавитьХарактеристикуНаСервере(ВидХарактеристики); КонецПроцедуры
В рамках асинхронной модели с использованием новых средств этот код будет выглядеть следующим образом:
Копировать в буфер обмена&НаКлиенте
Процедура ДобавитьХарактеристику(Команда)
//Выберем вид характеристики
Оповещение = Новый ОписаниеОповещения(
"ДобавитьХарактеристикуЗавершение",
ЭтотОбъект);
ОткрытьФорму("ПланВидовХарактеристик.ВидыХарактеристик.ФормаВыбора",
,,,,, Оповещение, РежимОткрытияОкнаФормы.БлокироватьВеcьИнтерфейс);
КонецПроцедуры
&НаКлиенте
Процедура ДобавитьХарактеристикуЗавершение(ВидХарактеристики, Параметры) Экспорт
Если ВидХарактеристики = Неопределено Тогда
Возврат;
КонецЕсли;
//Проверим наличие
Если ОписаниеХарактеристик.НайтиСтроки(
Новый Структура("ВидХарактеристики", ВидХарактеристики)).Количество() > 0 Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Характеристика уже существует!'", "ru"));
Возврат;
КонецЕсли;
//Добавим вид характеристики на форму
ДобавитьХарактеристикуНаСервере(ВидХарактеристики);
КонецПроцедуры
Следует обратить внимание, что процедура-обработчик объявлена экпортируемой. Это связано с тем, что эта процедура будет вызвана не кодом самого модуля, а системным кодом платформы, поэтому модуль должен предоставить к ней доступ.
Более сложной является ситуация, когда нужно о чем-то спросить пользователя во время обработчика события, например события закрытия формы. В асинхронной модели мы не можем сразу получить результат выбора, чтобы указать дальнейшие действия системе при помощи значения параметра Отказ.
В таких случаях доступен следующий алгоритм:
Ниже приведен пример кода, реализующего этот алгоритм:
Копировать в буфер обмена&НаКлиенте Перем ОтветПередЗакрытием; &НаКлиенте Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка) Если ОтветПередЗакрытием <> Истина Тогда Отказ = Истина; Оповещение = Новый ОписаниеОповещения( "ПередЗакрытиемЗавершение", ЭтотОбъект); ПоказатьВопрос(Оповещение, “Закрыть?”, РежимДиалогаВопрос.ДаНет); КонецЕсли КонецПроцедуры &НаКлиенте Процедура ПередЗакрытиемЗавершение(Результат, Параметры) Экспорт Если Результат = КодВозвратаДиалога.Да Тогда ОтветПередЗакрытием = Истина; Закрыть(); КонецЕсли; КонецПроцедуры
Теперь рассмотрим случай, когда выбор пользователя осуществляется в некоторой общей процедуре, вызываемой из разных мест другими процедурами. Получается, что в асинхронной модели такая процедура не может сразу вернуть результат, а должна как-то уведомлять вызывающие ее процедуры о том, что результат получен и можно продолжать работу.
Предположим, существует общая функция, которая возвращает текст, в зависимости от ответа пользователя:
Копировать в буфер обмена
&НаКлиенте Функция ПолучитьТекстВыбора() Результат = Вопрос("Продолжить операцию?", РежимДиалогаВопрос.ДаНет); Возврат ?(Результат = КодВозвратаДиалога.Да, "Продолжаем выполнять операцию...", "Операция прервана!"); КонецФункции
В асинхронной модели эту функцию и ее вызовы следует реализовывать следующим образом:
Копировать в буфер обмена&НаКлиенте Процедура ВыполнитьОперацию(Команда) Оп = Новый ОписаниеОповещения("ВыполнитьОперациюЗавершение", ЭтотОбъект); ПолучитьТекстВыбора(Оп); КонецПроцедуры &НаКлиенте Процедура ВыполнитьОперациюЗавершение(Результат, Параметры) Экспорт Сообщить(Результат); КонецПроцедуры &НаКлиенте Процедура ПолучитьТекстВыбора(ОбработкаОповещения) Контекст = Новый Структура("СледующееОповещение", ОбработкаОповещения); Оп = Новый ОписаниеОповещения("ПолучитьТекстВыбораЗавершение", ЭтотОбъект, Контекст); ПоказатьВопрос(Оп, "Продолжить операцию?", РежимДиалогаВопрос.ДаНет); КонецПроцедуры &НаКлиенте Процедура ПолучитьТекстВыбораЗавершение(Результат, Контекст) Экспорт Стр = ?(Результат = КодВозвратаДиалога.Да, "Продолжаем выполнять операцию...", "Операция прервана!"); Если Контекст <> Неопределено И Контекст.СледующееОповещение <> Неопределено Тогда ВыполнитьОбработкуОповещения(Контекст.СледующееОповещение, Стр); КонецЕсли; КонецПроцедуры
Таким образом, вызовы процедур можно связывать в цепочки, передавая им результат при помощи метода ВыполнитьОбработкуОповещения().
В статье были рассмотрены новые средства, позволяющие реализовывать более качественные приложения с использованием асинхронной модели, принятой в среде Интернет.
Несмотря на наличие таких средств, видно, что большое количество диалогов может усложнять программный код. К тому же, в веб-приложениях диалоги выбора используются гораздо реже, чем в настольных, поскольку снижают общее удобство использования.
В таких случаях имеет смысл рассмотреть другие подходы, не требующие использования диалогов. Например, использование сообщений, всплывающих подсказок вместо диалогов предупреждений.