Синонимы к словосочетанию «в порядке исключения»
Связанные слова и выражения
Делаем Карту слов лучше вместе
Привет! Меня зовут Лампобот, я компьютерная программа, которая помогает делать Карту слов. Я отлично умею считать, но пока плохо понимаю, как устроен ваш мир. Помоги мне разобраться!
Спасибо! Я обязательно научусь отличать широко распространённые слова от узкоспециальных.
Насколько понятно значение слова востренький (прилагательное):
Связанные слова (по тематикам)
- Люди: блюститель, педант, представитель, рядовой, неряха
- Места: быль, один, легислатура
- Предметы: том, экземпляр, глянец, вещь, рамка
- Действия: исключение, соблюдение, очерёдность, ограничение, отнесение
- Абстрактные понятия: порядок, правило, принцип, закон, устав
Ассоциации к слову «порядок»
Ассоциации к слову «исключение»
Предложения со словосочетанием «в порядке исключения»
- Здесь она вошла в портняжное ателье, где шили, вообще говоря, на мужчин, но в порядке исключения иногда снисходили до того, чтобы скроить костюм для особо привилегированных представительниц женского пола.
Цитаты из русской классики со словосочетанием «в порядке исключения»
- Тысячи народа ждали освящения барок на плотине и вокруг гавани. Весь берег, как маком, был усыпан человеческими головами, вернее, — бурлацкими, потому что бабьи платки являлись только исключением , мелькая там и сям красной точкой. Молебствие было отслужено на плотине, а затем батюшка в сопровождении будущего дьякона и караванных служащих обошел по порядку все барки, кропя направо и налево. На каждой барке сплавщик и водолив встречали батюшку без шапок и откладывали широкие кресты.
Сочетаемость слова «порядок»
Сочетаемость слова «исключение»
Значение слова «порядок»
ПОРЯ́ДОК , —дка, м. 1. только ед. ч. Состояние налаженности, организованности, благоустроенности; правильность, систематичность чего-л. Образцовый порядок. Полный порядок в делах. Нет порядка в доме. Привести тетради в порядок. (Малый академический словарь, МАС)
Значение слова «исключение»
ИСКЛЮЧЕ́НИЕ , -я, ср. 1. Действие по знач. глаг. исключить—исключать. Исключение из школы. (Малый академический словарь, МАС)
Афоризмы русских писателей со словом «порядок»
- На что бы походило,
Когда б в правлении, в каком бы то ни было,
Не с вышних степеней, а с нижних начинать
Порядок наблюдать?
Отправить комментарий
Дополнительно
Значение слова «порядок»
ПОРЯ́ДОК , —дка, м. 1. только ед. ч. Состояние налаженности, организованности, благоустроенности; правильность, систематичность чего-л. Образцовый порядок. Полный порядок в делах. Нет порядка в доме. Привести тетради в порядок.
Значение слова «исключение»
ИСКЛЮЧЕ́НИЕ , -я, ср. 1. Действие по знач. глаг. исключить—исключать. Исключение из школы.
Предложения со словосочетанием «в порядке исключения»
Здесь она вошла в портняжное ателье, где шили, вообще говоря, на мужчин, но в порядке исключения иногда снисходили до того, чтобы скроить костюм для особо привилегированных представительниц женского пола.
– Что ж, видимо, придётся пойти вам навстречу. Именно в порядке исключения. Давайте обсудим сроки и оплату.
Такое послабление послужило примером другим районам, поэтому отдельные состязания проводились в порядке исключения ещё более 30 лет.
Синонимы к слову «исключение»
исключение — существительное, имеет следующие синонимы:
- особенность
- выключение
- отчисление
- вычеркивание
- элиминация
- делистинг
- увольнение
- устранение
- вышибание
- выбрасывание
- выкидывание
- выпускание
- выставление
- вытуривание
- изъятие
- опущение
- пропускание
- опускание
- выписывание
- отступление
- удаление
- феномен
- убирание
- элиминирование
- единичный случай
- редкий случай
- редкая птица
- белая ворона
- антик
- паршивая овца
- редкость
- пропуск
- купюра
- эллипсис
- выпуск
- выключка
- выветь
Слово исключение входит в список слов на букву «И».
В качестве исключения выделяется запятыми или нет?
Вводные обороты и вводные слова формально не являются членами предложения, не связаны с ними синтаксически, а лишь комментируют логику изложения, служат для передачи авторских суждений. Они выделяются или отделяются запятыми в тексте. Например, Во-первых, нельзя лгать; Наверное, мы опоздали.
Но определить, является ли слово или конструкция вводными, иногда бывает достаточно сложно. В таких случаях важно учитывать смысловые особенности. Составить полный перечень вводных слов невозможно. Сравним: С другой стороны, так будет лучше. ‒ С другой стороны дома.
Конструкция «в качестве исключения» не является вводной, уточняющей либо пояснительной. В предложении она используется в качестве обстоятельства действия.
В качестве исключения учительница разрешила ребятам воспользоваться во время сочинения читательским дневником.
Экзаменационная комиссия не обратила внимания на опоздание студента только в качестве исключения.
Руководство гостиницы в качестве исключения предоставило нам номер повышенной комфортности.
http://synonymonline.ru/%D0%98/%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5
http://portalonline.ru/russkij-yazyk/6081-v-kachestve-isklyucheniya-vydelyaetsya-zapyatymi-ili-net.html
Нынешним летом порядок исключения недействующих фирм из ЕГРЮЛ заметно изменился. А некоторые важные изменения еще только предстоят, поскольку вступят в силу с 1 сентября 2017 года.
Нововведения коснутся:
- учредителей и директоров фирм, в отношении которых в ЕГРЮЛ внесена отметка о недостоверности данных;
- владельцев, которые ждут, когда их недействующую компанию исключат из ЕГРЮЛ, минуя процедуру ликвидации;
- кредиторов и контрагентов фирм, в отношении которых начата процедура банкротства.
Но давайте по порядку.
28 декабря прошлого года Владимир Путин подписал Закон № 488-ФЗ «О внесении изменений в отдельные законодательные акты Российской Федерации». А именно — в федеральные законы № 14-ФЗ «Об обществах с ограниченной ответственностью», № 129-ФЗ «О государственной регистрации юридических лиц и индивидуальных предпринимателей» и № 127-ФЗ «О несостоятельности (банкротстве)».
Что же изменилось?
С одной стороны, ФНС получила большую, чем раньше, свободу действий.
С 01.09.2017 налоговики получат право исключать юрлицо из ЕГРЮЛ спустя шесть месяцев после того, как в реестр внесена отметка о недостоверности имеющихся сведений (новая редакция ст. 21.1 Закона № 129-ФЗ).
Как известно, с начала 2016 года, после изменений, внесенных в ст. 9 Закона № 129-ФЗ, ФНС может проверять сведения о компании не только тогда, когда владельцы регистрируют ее или вносят в реестр изменения. Достаточно любых подозрений на недостоверность сведений в ЕГРЮЛ (массовый учредитель, массовый директор, массовый адрес), и может начаться проверка. Согласно Приказу ФНС России от 11.02.2016 № ММВ-7-14/72@, участие в ней самого проверяемого совсем не обязательно. Например, для осмотра помещения, в котором зарегистрирована компания, достаточно двух понятых или же видеозаписи.
Если налоговики не обнаружат компании по адресу, указанному в реестре, ее учредителям и руководству будет направлено письмо с требованием внести изменения в ЕГРЮЛ.
Если в течение 30 дней реакции на письмо не поступит, налоговая служба имеет право вносить в ЕГРЮЛ запись о недостоверности информации. И начнется отсчет шести месяцев, после истечения которых компания исчезнет из ЕГРЮЛ, если только в трехмесячный срок со дня опубликования решения о предстоящем исключении от юридического лица, кредиторов и иных лиц, чьи права и интересы затрагиваются в связи с исключением юридического лица из ЕГРЮЛ, не поступит заявление.
С 01.09.2017 вступает в силу положение о том, что заявления владельцев или кредиторов исключаемого из ЕГРЮЛ юридического лица, подаваемые в трехмесячный срок с момента публикации решения о предстоящем исключении, должны быть мотивированными (новая редакция ст. 21.1 Закона № 129-ФЗ).
Раньше этот термин не использовался. В текущей редакции ст. 21.1 Закона № 129-ФЗ гласит:
«3. Решение о предстоящем исключении должно быть опубликовано в органах печати, в которых публикуются данные о государственной регистрации юридического лица, в течение трех дней с момента принятия такого решения. Одновременно с решением о предстоящем исключении должны быть опубликованы сведения о порядке и сроках направления заявлений недействующим юридическим лицом, кредиторами или иными лицами, чьи права и законные интересы затрагиваются в связи с исключением недействующего юридического лица из единого государственного реестра юридических лиц (далее — заявления), с указанием адреса, по которому могут быть направлены заявления».
Видимо, под «мотивированностью» следует понимать детальное раскрытие сведений о том, каким именно образом исключение контрагента из ЕГРЮЛ наносит ущерб заявителям.
Форма заявления будет утверждена ФНС отдельно в ближайшее время.
С другой стороны, появились новые ограничения.
С 28.06.2017 запрещено исключать из ЕГРЮЛ банкротящиеся компании (новая редакция ст. 28 Закона № 127-ФЗ и ст. 5 Закона № 129-ФЗ).
Оператор Единого федерального реестра сведений о банкротстве обязан в трехдневный срок представлять в ФНС сведения о начале процедуры банкротства компании (о введении наблюдения, финансового оздоровления, внешнего управления, о признании должника банкротом и об открытии конкурсного производства). На ФНС, соответственно, возложена обязанность в трехдневный срок вносить полученные сведения в ЕГРЮЛ. И в этом случае принудительное исключение юридического лица из ЕГРЮЛ начинать нельзя.
Подчеркнем, юрлицо с долгами вполне может быть исключено из реестра. Долг перед бюджетом при этом будет признан безнадежным к взысканию. А вот что касается обязательств перед кредиторами, то тут все зависит от их расторопности в инициировании банкротства либо подаче заявления о приостановке процедуры исключения должника из ЕГРЮЛ.
Кроме этого, появился новый, «компромиссный» вариант исключения из ЕГРЮЛ.
С 01.09.2017 принудительный порядок исключения из ЕГРЮЛ может применяться «в случае невозможности ликвидации юридического лица ввиду отсутствия средств на расходы, необходимые для его ликвидации, и невозможности возложить эти расходы на его учредителей (участников) (новая редакция ст. 5 Закона № 129-ФЗ).
Данная норма уже закреплена в Гражданском кодексе РФ, теперь дело дошло и до закона о регистрации. При внимательном рассмотрении нетрудно заметить, что это промежуточный вариант между добровольной ликвидацией и принудительным исключением из ЕГРЮЛ, своеобразная альтернатива банкротству.
Детали его применения еще не ясны, но ясно, что участники исключаемого общества должны будут обосновать в налоговой свою неготовность брать на себя расходы по ликвидации.
Наконец, ужесточена ответственность владельцев исключаемой из ЕГРЮЛ компании.
Теперь исключение недействующего общества из ЕГРЮЛ может не отменять субсидиарной ответственности его участников или руководства по долгам компании — если они действовали, как сказано в законе, «недобросовестно или неразумно» (новая редакция ст. 3 Закона № 14-ФЗ «Об обществах с ограниченной ответственностью», действует с 28.06.2017).
Субсидиарная ответственность по обязательствам ликвидированного общества может быть наложена по заявлению кредитора.
Что делать, если вы контрагент проблемной компании?
Выявив наличие оснований для исключения из ЕГРЮЛ, регистрирующий орган принимает решение о предстоящем исключении. В течение трех дней с момента принятия такое решение публикуется в ЕГРЮЛ.
Если вы кредитор проблемной компании, вам нужно внимательнее отслеживать Контур.Фокус на предмет того, не появилось ли на карточке контрагента решение налоговой службы о предстоящем исключении его из ЕГРЮЛ. Напоминаем, на мотивированное опротестование дается три месяца.
Стоит проявлять большую активность в инициировании процедур банкротства «безнадежного» контрагента — это поможет удержать ФНС от исключения такого контрагента из реестра. Конечно, предъявлять требования можно и после ликвидации — именно об этом написано абзацем выше. Но это, как вы понимаете, процедура совершенно не отработанная, и в любом случае шансов на взыскание долга в этом случае будет меньше.
Что делать, если вы владелец или директор «зависшей» компании?
Уйти от долгов, просто забыв про общество, уже не получится.
Во-первых, если фирма исключена из ЕГРЮЛ при наличии задолженности в бюджет, признанной безнадежной к взысканию, ее учредители и руководитель в течение трех лет не смогут зарегистрироваться в качестве учредителей и руководителей других организаций (пп. «ф» п. 1 ст. 23 Федерального закона от 08.08.2001 № 129-ФЗ, действует с 1 января 2016 года).
Во-вторых, если долги остались перед контрагентами, их можно будет взыскивать в порядке субсидиарной ответственности (об этом мы уже написали выше).
В-третьих, в период ожидания руководитель рискует набрать административных штрафов по ст. 119 (непредставление декларации), 126 (непредставление сведений и документов по требованию ИФНС) НК РФ и по ст. 13.19 (непредставление данных в Росстат), 15.5 (нарушение сроков представления декларации) КоАП РФ.
Вывод: пассивно дожидаться исключения своей фирмы из ЕГРЮЛ не стоит. Заплатить по долгам в той или иной форме все равно придется.
А можно ли обжаловать исключение из ЕГРЮЛ?
Да, можно, через арбитражный суд. Это могут сделать не только владельцы исключенной компании, но и ее кредиторы и вообще все лица, чьи права затронуты исключением. Заявление можно подать в течение трех месяцев с момента, когда стало или должно было стать известно о нарушении права (п. 4 ст. 198 АПК). Пропущенный по уважительной причине срок подачи заявления может быть восстановлен судом.
Решение налоговой об исключении из ЕГРЮЛ может быть отменено по следующим основаниям:
- у ИФНС отсутствовали основания для исключения;
- заявление об отмене решения подавалось в пределах трехмесячного срока (оно было обоснованным и с соблюдением формы);
- ИФНС нарушила процедуру исключения, описанную в законе.
Как видите, исключение из ЕГРЮЛ теперь проходит в новых условиях. Если для вас важно повлиять на действия ФНС, нужно проявлять повышенное внимание к изменениям открытых данных. Пользуясь нашим сервисом, вы сможете отследить, не нависла ли угроза исключения из ЕГРЮЛ над одним из ваших контрагентов.
На чтение 8 мин Просмотров 1.6к. Опубликовано 21.03.2022
Если вас волнует вопрос: «за исключением» выделяется запятыми или нет, сразу ответим, что это не вводное сочетание, требующее обособления. Однако знаки в предложениях с предлагаемым к рассмотрению словосочетанием могут присутствовать, если оно входит в состав некоторых конструкций, о которых поговорим ниже.
Часть речи и роль в предложении «за исключением»
Предлог
В роли составного отыменного предлога данное сочетание встречается в предложениях довольно часто. Оно указывает на предмет или феномен, являющийся исключением в ряду других. Может быть заменен синонимами: «кроме», «помимо», «за вычетом», «не считая» что-либо или кого-либо. Предлог называется составным, если состоит из нескольких слов. Отыменным он зовется, так как образован от существительного «исключение».
Рассматриваемый предлог связан с местоимением или существительным в форме Родительного падежа, которые отвечают на вопросы: «чего?», «кого?».
Данный предлог обычно входит в состав оборотов со значением исключения, замещения (ограничительно-выделительные обороты), которые обособляются запятыми. Сам предлог обычно не выделяется знаками.
Существительное с предлогом
Если внутри искомого сочетания можно вставить прилагательное или местоимение, тогда, скорее всего, перед нами не составной предлог, а существительное с предлогом в форме творительного падежа, которое отвечает на вопрос: «за чем?». В этом случае существительное употребляется в значении: «устранение», «увольнение», «отчисление», «удаление», «изгнание». На письме не выделяется запятыми.
Выделение «за исключением» запятыми
Постановка знаков в предложениях с составным предлогом зависит от смысла, заложенного автором и от контекста. Однако рассмотрим некоторые закономерности, позволяющие определить, где знак нужен, а где его можно опустить.
С двух сторон
Выделяем оборот знаками с обеих сторон, если он находится в середине предложения. Обособление осуществляется для того, чтобы обозначить границы оборота и исключить двусмысленность фразы. Напомним, что составной предлог не требует отдельного обособления знаками.
Пример:
- Вчера, за исключением меня, тебя на конференции никто не слушал.
Знаки обязательны, если оборот находится внутри грамматической основы, то есть между подлежащим и сказуемым.
Пример:
- Все студенты, за исключением Овечкина и Сидорова, явились на экзамен. (грамматическая основа – «студенты явились»)
Обозначаем границы пояснительного оборота запятыми, если он разрывает связь управляющего и зависимого слова.
Примеры:
- Почти все работники собрались, за исключением механика Синицына, в коридоре для обсуждения нового предложения начальства.
- Лимоны содержат, за исключением В12, всю гамму витаминов группы В, необходимых для поддержания молодости и бодрости.
Перед сочетанием
Запятая ставится перед сочетанием, если оборот имеет пояснительное значение и находится в конце предложения.
Пример:
- Все гости поздравили именинника, за исключением опаздывающих Муравьевых.
После сочетания
Правила не регулируют постановку знаков препинания после исследуемого словосочетания, однако запятая может присутствовать, если того требует словесное окружение. То есть, знак относится к слову или обособляемой конструкции, стоящей рядом.
Пример:
- Татьяну всегда преследовали неудачи. За исключением, вероятно, детских лет, она всегда ощущала беспокойство, напряжение, страх. (запятая относится к вводному слову «вероятно»)
Когда «за исключением» не выделяется запятыми?
- За исключением мытья посуды всю работу мы сделали.
Однако если оборот весьма распространен и содержит вводные слова, перечисления, тогда запятые нужны для упрощения восприятия фразы и расстановки границ конструкции.
Пример:
- За исключением, наверное, поломки автомобиля, во время нашего путешествия не происходило никаких непредвиденных ситуаций.
- За исключением царапин на коленях, локтях, ладонях, падение с дерева ребенок пережил, к счастью, без серьезных травм.
Также запятая может присутствовать, если автор желает интонационно выделить оборот.
- За исключением карт, в потерянном кошельке ничего не было.
Никогда не ставится запятая для выделения падежного сочетания – существительного с предлогом.
Рассмотрим пример:
- За исключением ученика из общеобразовательного заведения последовали другие неприятные процедуры и обращение родителей в Департамент образования.
- За громким исключением из института следили все преподаватели. (внутри сочетания находится прилагательное)
Также не выделяется запятыми ограничительно-выделительный оборот, если он тесно связан со сказуемым.
Пример:
- Все вернулись за исключением Пети.
Примеры предложений для закрепления материала
«за редким исключением»
Отдельного внимания заслуживает данное выражение, которое в предложении может выполнять функцию вводного. Существуют и другие его вариации «за небольшим исключением», «за некоторыми исключениями». Смысл остается тот же. Отметим, что изречение не требует наличия зависимых слов в Родительном падеже. Обособляется оно с двух сторон запятыми.
Примеры:
- Учитель был очень рад, что все в классе, за редким исключением, отлично справились с заданием.
- Все пункты плана, за некоторыми исключениями, были выполнены в срок.
Заметим, что в приведенных примерах сочетание разделяет грамматическую основу.
«в виде исключения»
Для начала отметим, что это устойчивое выражение пишется в три слова. Обособляется запятыми в зависимости от контекста.
Рассмотрим примеры:
- Приняли Вас в коллектив только в виде исключения, о чем сегодня сожалеем. (запятая относится к придаточной части предложения, присоединяемой союзом «о чем?»)
- На встречу ректоров в виде исключения был допущен профессор Соколов. (запятые не нужны)
- Все массовые мероприятия отменяются. Может быть, мы согласимся, в виде исключения, организовать детям праздник. (сочетание выполняет функцию вводного, при произношении оно сопровождается интонационной паузой)
«в качестве исключения»
Данное словосочетание, как и предыдущие, схоже по значению с выражением, рассматриваемым в этой статье. По-другому можно сказать «в порядке исключения». Перед нами обстоятельство образа действия, второстепенный член предложения, отвечающий на вопрос «как?». Оно обозначает способ действия, то есть несет дополнительную информацию о том, как именно оно совершается. Обычно встречается в текстах официально-делового стиля и не требует обособления.
Примеры:
- Сегодня у нас выходной, жалоба пенсионерки была рассмотрена в качестве исключения.
- Пострадавшим выделят премию в порядке исключения.
В некоторых случаях сочетание «в порядке исключения» выделяется запятыми. Отметим, что зачастую постановка запятых факультативна и зависит от пожеланий автора. Все же стоит придерживаться правил, изложенных выше.
Управление по исключениям ( MBE ) — это стиль управления бизнесом, который фокусируется на выявлении и обработке случаев отклонения от нормы, рекомендованных в качестве наилучшей практики методом управления проектами.
Управление по исключениям имеет как общее бизнес-приложение, так и приложение бизнес-аналитики. Общие бизнес-исключения — это случаи, которые отклоняются от нормального поведения в бизнес-процессе и требуют особого подхода, обычно с вмешательством человека. Их причина может включать: отклонение процесса, проблемы с инфраструктурой или подключением, внешнее отклонение, низкое качество бизнес-правил , искаженные данные и т. Д. Управление в порядке исключения — это практика расследования, разрешения и обработки таких случаев с использованием квалифицированного персонала и программных инструментов. Хорошее управление может способствовать эффективности бизнес-процессов. Часто в этих случаях процесс будет называться управлением исключениями, поскольку исключительные случаи не являются единственной целью политики управления, а управление исключениями (в отличие от управления исключениями) означает более умеренное применение процесса.
Управление в порядке исключения дает сотрудникам возможность самостоятельно принимать решения и выполнять свою работу или проекты. Он состоит из сосредоточения и анализа статистически значимых аномалий в данных. Если возникает необычная ситуация или отклонение в записанных данных, которые могут вызвать трудности для бизнеса и не могут быть устранены сотрудником на его уровне, сотрудник должен передать решение на следующий более высокий уровень. Например, если все продукты продаются в ожидаемых объемах за квартал, за исключением одного конкретного продукта, который демонстрирует низкие или высокие показатели со статистически значимой маржой, только данные по этому продукту будут представлены менеджерам для дальнейшего изучения и обнаружения первопричина. Управление в порядке исключения может выявить ошибки и упущения в бизнесе, неэффективные стратегии, которые необходимо улучшить, изменения в конкуренции и деловых возможностях. Управление в порядке исключения предназначено для снижения управленческой нагрузки и предоставления менеджерам возможности более эффективно тратить свое время в тех областях, где оно будет иметь наибольшее влияние. Эта концепция управления широко приписывается Фредерику В. Тейлору и впервые обсуждалась в его работе « Управление цехом: доклад, прочитанный перед Американским обществом инженеров-механиков . Нью-Йорк: Американское общество инженеров-механиков.
Управление исключениями также имеет ИТ-приложение. Если при написании кода программист видит, что будет исключительный случай, когда предопределенное предположение о приложении будет нарушено, программист должен будет иметь дело с этим исключением программно с самого начала.
Процесс управления в порядке исключения
Прежде всего, необходимо установить цели или нормы с предсказуемыми или предполагаемыми результатами. Эти характеристики оцениваются и приравниваются к фактическим. Затем анализируется отклонение. При незначительном отклонении или его отсутствии никаких действий не требуется, и руководители высшего звена могут сосредоточиться на других вопросах. Если фактические показатели значительно отличаются, проблему необходимо передать старшим менеджерам, поскольку «произошло исключение». Наконец, цель состоит в том, чтобы немедленно устранить это «исключение».
Управление в порядке исключения с использованием дисперсионного анализа
Бухгалтерия отвечает за прогнозирование бюджетов и отчеты об исполнении затрат. Разница между расчетными и фактическими цифрами определяется как отклонение. Чтобы понять причину разницы, менеджерам необходимо изучить вопросы, чем отличается разница по сравнению с прошлым периодом и каковы причины недостижения оценочных показателей. Анализаторы рассматривают два типа дисперсии: неблагоприятная дисперсия и благоприятная дисперсия. Неблагоприятное отклонение «существует, когда разница между заложенной в бюджет и фактической цифрой приводит к более низкой, чем ожидалось, прибыли». Благоприятная разница «существует, когда разница между заложенной в бюджет и фактической цифрой приводит к более высокой, чем ожидалось, прибыли». Вместо того, чтобы рассматривать все отклонения, менеджеры устанавливают критерии, чтобы определить, на каких отклонениях следует сосредоточить внимание. Управление в порядке исключения сосредотачивается в основном на больших неблагоприятных отклонениях, чтобы найти области бизнеса, которые отклоняются от заранее установленных стандартов в негативном направлении.
Активное управление по исключениям и пассивное управление по исключениям
Рассматривая управление по принципу исключения и пытаясь определить, где находится набор навыков или какому стилю они следуют, важно помнить, что этот метод лидерства включает два разных пути.
Во-первых, активное управление в порядке исключения, когда лидер активно помогает в решении проблем, активно участвует и наблюдает за подчиненными, чтобы предотвратить ошибки. Во-вторых, пассивное управление в порядке исключения. В этом методе менеджер вмешивается только тогда, когда стандарты не соблюдаются, и действия должны быть предприняты, обычно после того, как что-то произошло, а не в процессе.
Любой подход имеет смысл, но его нельзя определить, пока вы не разберетесь в своей среде. В непринужденной, непринужденной обстановке, где люди понимают свои роли и, соответственно, являются малыми и средними предприятиями, более пассивный подход может способствовать повышению морального духа группы и чувству независимости. В более жесткой, менее простой среде с людьми, которые только начинают исполнять свою роль или не полностью понимают задачи, более активная позиция, скорее всего, окажется более выгодным путем, поскольку пошаговое руководство может повысить компетентность. , а также уверенность.
Преимущества управления в порядке исключения
Основное преимущество управления по принципу исключения состоит в том, что проблемные вопросы выявляются быстро, и менеджеры могут более разумно использовать свое время и энергию для решения важных вопросов, а не менее важных, которые могут спровоцировать задержки в их повседневных операциях. Кроме того, менеджерам нужно меньше работать со статистикой, и частота принятия решений становится меньше, что экономит время. Поскольку менеджеры принимают меньше решений, на сотрудников ложится больше ответственности, что повышает их мотивацию.
Недостаток управления по исключениям
Возникновение ошибок при расчете бюджетов приводит к большим отклонениям, и поиск ошибок может занять много времени (а значит, дорого). Кроме того, финансовые аналитики, отвечающие за расчет отклонений, увеличивают накладные расходы компании. Если финансовые аналитики не работают хорошо, это станет пустой тратой времени и денег. Другой недостаток заключается в том, что только менеджеры имеют право принимать действительно важные решения, что может демотивировать сотрудников на более низком уровне. Кроме того, требуется время, чтобы передать проблемы менеджерам. Управление сотрудниками, которые отклоняются от обычных процедур из-за несоблюдения нормативных требований, считается трудным для управления и, как правило, сталкивается с ограниченными должностными обязанностями и в конечном итоге увольняется / увольняется.
использованная литература
- Биттель, Лестер Р. (1964). Управление по исключениям; Систематизация и упрощение управленческой работы . Нью-Йорк: Макгроу-Хилл.
- Гарднер, Фред В. (1940). Контроль переменного бюджета посредством управления исключениями и динамическими затратами . Нью-Йорк: McGraw-Hill Book Co.
- Макинтош, Дональд П. (1978). Управление исключениями: Справочник с формами . Энглвуд Клиффс, Нью-Джерси: Прентис-Холл.
внешние ссылки
- Управление по исключению в PRINCE2 wiki
На последней конференции Инфостарт в ноябре 2021 выступал с докладом по асинхронным методам наш автор Василий Ханевич (курсы по запросам, СКД, администрированию, расширениям и т.д.).
Считаем полезным поделиться детальным разбором их работы. Сядьте поудобнее, это реальный лонгрид на 53 страницы текста А4
Что здесь важно – у 1С давно ничего не менялось в языке 1С, но сейчас появился новый тип данных (“Обещания”), новые асинхронные функции – и это само по себе интересно.
Впрочем, поехали!
Содержание
В данной статье рассмотрим отличия синхронных вызовов от асинхронных, разберем, почему потребовалось отказываться от синхронных методов, а также изучим новшества технологии работы с асинхронными вызовами, которые реализованы в платформе 8.3.18.
Навигация
- Введение. Зачем вообще потребовались асинхронные методы в платформе “1С:Предприятие 8”?
- Отказ от модальности
- Асинхронные вызовы расширений и внешних компонент
- Синхронные методы
- Асинхронные методы
- Использование методов обратного вызова
- Принцип работы методов обратного вызова
- Пример 1 – Организация диалога с пользователем
- Пример 2 – Сохранение файла на клиентском компьютере
- Вложенные процедуры с асинхронными методами
- Сложности при использовании методов обратного вызова
- Инструменты рефакторинга
- Создать обработку оповещения
- Преобразовать вызов
- Найти вызовы модуля
- Анализ нерекомендуемых синхронных вызовов конфигурации
- Использование обещаний
- Новый тип – Обещание
- Асинхронные функции
- Работа с асинхронными функциями
- Модификатор Асинх
- Обработка исключений в асинхронных процедурах и функциях
- Примеры использования асинхронных функций
- Организация диалога с пользователем
- Копирование файла
- Проверка возможности работы с внешней системой
- Вопрос пользователю во время закрытия формы
- Ошибки при использовании асинхронных функций в коде
- Ошибка 1 – Только клиентский контекст
- Ошибка 2 – Оператор Ждать только в асинхронных методах
- Ошибка 3 – Подходящие версии платформы
- Принципы работы асинхронных функций
- Особенности использования отладчика при работе с асинхронными функциями
- Использование фоновых заданий для выполнения длительных операций
- Заключение
- База с приведенными в статье фрагментами кода
Введение. Зачем вообще потребовались асинхронные методы в платформе “1С:Предприятие 8”?
Конфигурации на платформе “1С:Предприятие 8” могут работать на различных клиентских устройствах, например, через тонкий клиент на компьютерах под управлением ОС Windows, Linux, MacOS или через веб-клиент через Internet Explorer, Edge, Mozilla Firefox, Google Chrome или Safari. Каждый из этих вариантов имеет свои особенности – значит со стороны платформы должна быть реализована поддержка большого количества вариантов работы.
Стоит выделить поддержку работы через веб-клиент – удобный для пользователей режим, поскольку им не нужно устанавливать дополнительные программы.
Через браузер можно работать с почтой, облачными хранилищами, банковскими системами и огромным количеством других приложений. Поскольку важно обеспечить безопасность пользователя, надежность и высокую скорость, разработчики браузеров предъявляют жесткие требования к веб-сайтам и технологиям, к тому же эти требования меняются с течением времени.
Фирма “1С” уделяет большое внимание поддержке современных версий браузероы, в платформу вносятся изменения, которые диктуются разработчиками браузеров.
Рассмотрим несколько примеров.
Отказ от модальности
В качестве примера можно привести отказ от модальности, которому посвящена отдельная статья на нашем сайте. Такой вариант работы интерфейса появился в платформе 8.3.3 (июль 2013 года). Для того, чтобы обеспечить работу с базами 1С через браузер, в том числе на мобильных устройствах, потребовалось отказаться в конфигурациях от использования модальных окон, которые при открытии блокируют весь интерфейс браузера, включая остальные открытые окна и вкладки.
В чем заключается недостаток модальных окон в браузерах? Дело в том, что всплывающие окна в Интернете часто используются для распространения нежелательной рекламы, поэтому браузеры содержат функции блокировки всплывающих окон.
Поэтому рекомендуется использовать блокирующие окна вместо модальных. Блокирующее окно как бы “рисуется” поверх главного окна, блокируется только текущая вкладка браузера, в которой открыта конфигурация, позволяя переключаться на другие вкладки, поскольку модальные окна браузера при этом не используются.
Для пользователя внешне все выглядит так же, как и с использованием модальных окон. Но разработчикам на платформе “1С:Предприятие” пришлось переработать программный код с использованием новых неблокирующих методов, чтобы конфигурация корректно работала в веб-клиенте. А фирме “1С” необходимо было реализовать соответствующие методы в платформе, учитывая требования, диктуемые разработчиками браузеров.
Асинхронные вызовы расширений и внешних компонент
Рассмотрим еще один пример, демонстрирующий, что требования браузеров могут влиять на программный код в конфигурациях на платформе “1С:Предприятие”.
В сентябре 2013 года было опубликовано, что с января 2014 года браузер Google Chrome по умолчанию будет блокировать плагины NPAPI, а в итоге поддержка NPAPI будет полностью удалена из Chrome. И действительно в сентябре 2015 года был выпущен Google Chrome (версия 45), который перестал поддерживать эту технологию на всех ОС. Аналогично поступили и разработчики других браузеров – Opera, Firefox, Safari, Internet Explorer теперь также не поддерживают NPAPI.
NPAPI (Netscape Plugin Application Programming Interface) – это технология разработки дополнительных модулей (плагинов) для различных браузеров. В качестве примеров можно привести Adobe Flash Player, Microsoft Silverlight, Java Runtime Environment.
В чем же причина отказа от поддержки этой технологии? Ее архитектура была разработана еще в 90-х годах XX века. На сегодняшний день она устарела, могла становиться причиной зависаний и сбоев, были выявлены проблемы, связанные с безопасностью. Кроме этого NPAPI не поддерживается на мобильных устройствах.
В качестве альтернативы компания Google предлагает применять технологию Native Messaging. Принципиально важной особенностью этой технологии является обязательное использование асинхронных методов.
Может возникнуть вопрос – какое отношение используемые в браузерах технологии могут иметь к программному коду на встроенном языке “1С:Предприятие”?
Дело в том, что при использовании веб-клиента для работы с файлами, криптографией, буфером обмена и внешними компонентами требуется установить расширение для браузера. Следовательно, это расширение должно поддерживать актуальные технологии. Поэтому фирма “1С” внесла изменения в платформу 8.3.5 и реализовала для методов встроенного языка, которые использовали технологию NPAPI, аналогичные асинхронные методы. Например, вместо метода ПолучитьФайлы теперь нужно применять НачатьПолучениеФайлов. А разработчикам конфигураций в очередной раз пришлось переработать программный код.
Таким образом, современные браузеры диктуют ряд изменений, которые приходится вносить в платформу. Также видно, что все чаще используются асинхронные методы. Поэтому теперь нужно детально разобраться, что же такое синхронный и асинхронный код, в чем их отличия, а также понять, почему возникла необходимость использовать именно асинхронные методы в конфигурациях.
Синхронные методы
С самых первых версий платформы “1С:Предприятие” в каждом отдельном сеансе программный код, написанный на встроенном языке, исполняется строго последовательно. Это и называется синхронным исполнением программного кода, а соответствующие методы встроенного языка – синхронными.
Интерпретатор встроенного языка получает очередную команду для исполнения, приступает к ее выполнению. Этот процесс занимает какое-то время, после чего возвращается результат. Затем интерпретатор может переходить к следующей команде. И так до тех пор, пока все команды не будут выполнены.
Рассмотрим пример программного кода:
Счетчик = 1; ТекстСообщения = "Сообщение"; Сообщить(ТекстСообщения);
Он выполняется пошагово:
- Первым делом будет выполнено присваивание переменной Счетчик значения 1.
- Осуществляется переход ко второй строке кода, выполняется операция присваивания.
- Осуществляется переход к третьей строке кода, выводится сообщение пользователю.
Таким образом, в каждый конкретный момент времени исполняется только одно действие, а несколько действий в рамках одного сеанса не могут выполняться одновременно.
Здесь можно привести аналогию с лентой конвейера, которая по одной, друг за другом, поставляет детали для обработки на оборудовании:
Аналогично интерпретатор встроенного языка поочередно выполняет поступающие команды:
Важно отметить, что выполняющийся синхронный метод блокирует основной поток выполнения кода до тех пор, пока этот метод не завершится. Если в ходе выполнения этот метод вызывает другие процедуры или функции, то необходимо будет дождаться их выполнения.
Поэтому такой код и называется синхронным – вызывающий и вызываемый код согласованы (синхронизированы) по времени, т.е. вызывающий метод не будет исполняться в то время, когда исполняется вызванный метод. Когда вызванный метод завершится, управление вернется к вызывающему методу, он может продолжить свое выполнение. В этом и заключается синхронизация.
В процессе выполнения метода могут использоваться сложные вычисления, занимающие много времени. Выход из этого метода не будет произведен до тех пор, пока работа этого метода не будет завершена. Для пользователя это будет выражаться в том, что приложение не будет реагировать на действия пользователя, курсор изменит свой вид:
Если в программном коде используется метод, который требует реакции пользователя (вопрос или предупреждение), то поток выполнения кода будет заблокирован до тех пор, пока пользователь не ответит на вопрос или не закроет окно с предупреждением.
Пусть есть следующий программный код:
Ответ = Вопрос("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); Сообщить("Начало загрузки");
Метод Вопрос является синхронным, т.е. блокирует поток выполнения команд. Значит, платформа не перейдет к выполнению следующей команды (не выведет сообщение) до тех пор, пока пользователь не ответит на вопрос.
При работе в тонком клиенте такое поведение не является проблемой, система будет ожидать ответа пользователя, после чего выполнение кода продолжится. Но при работе в веб-клиенте существует ряд ограничений, которые накладываются браузерами.
Веб-клиент написан на JavaScript. Движок JavaScript в браузере работает по следующей логике: он ожидает поступления задач к выполнению, поочередно, последовательно выполняет их и затем снова ожидает появления следующей задачи. Примерами задач может быть выполнение скрипта на веб-странице, выполнение обработчиков событий (нажатие пользователем кнопок на клавиатуре, движение мышью и т.д.). Подобный способ обработки задач называется событийным циклом (англ. – Event Loop).
JavaScript фактически является однопоточным. Если задача выполняется продолжительное время, браузер в это же время не сможет обрабатывать пользовательские события, возможно “зависание” браузера. Другими словами, в основном потоке может происходить что-то одно – или исполняется код на языке JavaScript, или браузер реагирует на действия пользователя.
Поэтому в браузерах существуют ограничения на время работы скриптов. Это своего рода защита от скриптов, которые выполняются слишком долго. С ее помощью браузеры предотвращают блокировку интерфейса.
Рассмотрим пример. Пусть есть такой HTML-документ:
<html> <body> <button onclick="LongTermCalculation()">Длительная операция</button> <script type="text/javascript"> function LongTermCalculation() { var res = 0; for (var i = 0; i < 10000000000; i++){ res += Math.sin(i); } alert(res); } </script> </body> </html>
На странице располагается кнопка, при нажатии на которую исполняется код на JavaScript. В этом коде на каждой итерации цикла вычисляется синус от значения счетчика цикла. Это достаточно длительная операция, поскольку требуется выполнить 10 миллиардов итераций цикла. Поэтому браузер периодически проверяет, не завис ли выполняемый скрипт, задает пользователю вопрос, не следует ли прервать его выполнение. Например, в Mozilla Firefox такой вопрос выглядит следующим образом:
Одним из способов решения описанной проблемы является использованием асинхронных методов, которые предназначены для предотвращения блокировки основного потока. Асинхронные методы могут быть реализованы в JavaScript, а также в других языках – Python, C#.
Рассмотрим асинхронные методы подробнее.
Асинхронные методы
Синхронный метод блокирует основной поток выполнения кода до тех пор, пока этот метод не завершится, включая все процедуры и функции, которые из этого метода вызываются. Браузеры, как было рассмотрено выше, имеют ограничения на выполнение синхронных методов. Например, современные браузеры не позволяют выполнять операции с файловой системой клиентского компьютера в синхронном режиме.
Поэтому были придуманы асинхронные методы – это такие методы, выполнение которых не происходит синхронно с кодом, из которого они вызваны. В этом случае нет синхронизации по времени между вызывающим и вызываемым кодом. Вызывающий метод не дожидается завершения вызванного метода, а продолжает свое выполнение после вызова асинхронного метода. За счет этого не блокируется основной поток выполнения кода.
Перепишем программный код на встроенном языке из прошлой главы, заменив синхронный вызов на асинхронный:
ПоказатьВопрос(Новый ОписаниеОповещения("ПоказатьВопросЗавершение", ЭтотОбъект), "Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); Сообщить("Начало загрузки");
Метод Вопрос является синхронным, а метод ПоказатьВопрос – асинхронным. После вызова асинхронного метода управление вернется к коду, вызвавшему этот метод, до того, как сам асинхронный метод ПоказатьВопрос отработает. Таким образом, асинхронный метод не блокирует основной поток. Поэтому сообщение о начале загрузки будет показано еще до того, как пользователь ответит на вопрос.
Когда вызванный асинхронный метод завершит свою работу (пользователь ответит на заданный вопрос), он оповестит о своем завершении и предоставит доступ к результату (в данном случае это будет информация о том, какую кнопку в диалоговом окне нажал пользователь: Да или Нет). Это событие можно обработать – в зависимости от нажатой пользователем кнопки выполнить то или иное действие.
Для того, чтобы система знала, что нужно сделать при завершении работы асинхронного метода, первым параметром метода ПоказатьВопрос указывается специальный объект встроенного языка ОписаниеОповещения, которое и представляет собой описание процедуры, которую нужно вызвать после того, как пользователь ответит на вопрос. Подробнее про этот объект поговорим в следующем разделе.
Асинхронные методы встроенного языка можно использовать, например, в следующих сценариях:
- Работа с блокирующими окнами:
- Задать вопрос пользователю;
- Показать предупреждение;
- Открыть окно, блокирующее интерфейс, и обработать результат закрытия этого окна
- Работа с файлами и каталогами:
- Получить файл с сервера;
- Получить каталог временных файлов;
- Скопировать файлы;
- Удалить файлы
- Работа с механизмами криптографии:
- Получить перечень сертификатов;
- Проверить сертификат;
- Проверить действительность подписи;
- Зашифровать данные;
- Расшифровать зашифрованные данные
- Работа с внешними компонентами:
- Подключить внешнюю компоненту;
- Обратиться к ее свойствам и методам.
В качестве примера асинхронных методов встроенного языка можно привести клиентские методы для работы с файлами, поскольку в веб-клиенте доступны только асинхронные методы работы с файлами. Поэтому вместо синхронного метода КопироватьФайл следует использовать асинхронные аналоги НачатьКопированиеФайла или КопироватьФайлАсинх, вместо синхронного метода ПолучитьФайлы – НачатьПолучениеФайловССервера или ПолучитьФайлыССервераАсинх и т.д.
Обратите внимание, что указанные асинхронные методы доступны только на клиенте. На сервере доступны аналогичные синхронные методы для работы с файлами, криптографией и внешними компонентами.
JavaScript имеет развитый функционал для работы с асинхронными методами. Особенно часто асинхронный код применяется при получении данных или для доступа к внешним устройствам – получение файлов с удаленных серверов, получение данных из базы, доступ к видео с веб-камеры.
Таким образом, некоторые приемы программирования на JavaScript теперь можно применять при разработке на платформе “1С:Предприятие”. Во встроенном языке существуют схожие способы реализации асинхронности, которые уже давно присутствуют в JavaScript:
- Использование методов обратного вызова (callback)
- Использование Обещаний (promise)
В следующих главах подробно рассмотрим эти приемы.
Использование методов обратного вызова
Принцип работы методов обратного вызова
После вызова асинхронного метода управление вернется к коду, вызвавшему этот метод, не дожидаясь, когда асинхронный метод завершит свою работу. Когда вызванный асинхронный метод отработает, он оповестит о своем завершении и предоставит доступ к результату. Оповещение о завершении происходит при помощи вызова процедуры, описание которой передается в асинхронно вызываемый метод. Эта процедура и называется методом обратного вызова (англ. callback – дословно “обратный звонок”), поскольку позволяет асинхронному методу “связаться” с вызвавшим его кодом:
Во многих языках программирования, в том числе и в JavaScript (на котором написан веб-клиент), можно передавать функцию как параметр другой процедуры. Рассмотрим подробнее на примере.
Пусть есть следующий код на языке JavaScript:
console.log('1'); console.log('2'); console.log('3');
Этот код последовательно выводит в консоль числа 1, 2 и 3. Это синхронный код.
Теперь модифицируем его – реализуем вывод числа 2 в консоль по таймеру, через 2 секунды:
console.log('1'); setTimeout(LogTwoSecondsLater, 2000); console.log('3'); function LogTwoSecondsLater() { console.log('2') }
Функция setTimeout ожидает 2 секунды (вторым параметром функции указан период ожидания в миллисекундах: 2000 мс = 2 с), а затем вызывает функцию обратного вызова LogTwoSecondsLater, переданную в качестве первого параметра. Функция setTimeout не блокирует основной поток. Скрипт не “зависнет” на 2 секунды, а продолжит выполнение. В консоль будут выведены числа 1, 3. И только через 2 секунды, когда сработает таймер, будет вызвана функция LogTwoSecondsLater, в консоль будет выведено число 2.
Но во встроенном языке “1С:Предприятие” нельзя указывать функцию в качестве параметра другого метода. Поэтому приведенный ниже код иллюстрирует логику работы асинхронных функций с использованием метода обратного вызова, но является синтаксически некорректным:
Процедура ДлительнаяЗагрузка() ЗагрузитьАсинхронно(ВыполнитьДействияПослеЗагрузки); КонецПроцедуры Процедура ЗагрузитьАсинхронно(МетодОбратногоВызова) //Действия для загрузки данных... МетодОбратногоВызова(); КонецПроцедуры Процедура ВыполнитьДействияПослеЗагрузки() //Оповещение, что загрузка завершена. Действия после завершения загрузки... КонецПроцедуры
Во встроенном языке асинхронный код с использованием методов обратного вызова реализован при помощи объекта ОписаниеОповещения. Этот объект содержит описание метода обратного вызова:
- Какую процедуру нужно выполнить после завершения асинхронного метода?
- В каком модуле она располагается?
- Какие параметры нужно в нее передать?
Для того, чтобы правильно составить описание метода обратного вызова, корректно описать все необходимые параметры, удобно использовать Синтакс-помощник. В нем указаны все параметры метода обратного вызова, который будет выполнен при завершении асинхронного метода.
Например, для метода ПоказатьВопрос после ответа пользователя на вопрос будет вызвана процедура со следующими параметрами:
- РезультатВопроса
- ДополнительныеПараметры
Пример 1 – Организация диалога с пользователем
Рассмотрим пример. В нем задается вопрос пользователю, на который он может ответить Да или Нет. После того, как пользователь ответит на вопрос, в сообщении выводим, сколько времени ему потребовалось на ответ.
Для реализации такого функционала используется следующий код в модуле формы:
&НаКлиенте Процедура ЗадатьВопрос(Команда) ДопПараметры = Новый Структура("ВремяНачала", ТекущаяДата()); ОписаниеОповещения = Новый ОписаниеОповещения("ПоказатьВопросЗавершение", ЭтотОбъект, ДопПараметры); ПоказатьВопрос(ОписаниеОповещения, "Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); Сообщить("Начало загрузки"); КонецПроцедуры &НаКлиенте Процедура ПоказатьВопросЗавершение(РезультатВопроса, ДополнительныеПараметры) Экспорт Сообщить("Выбран вариант: " + РезультатВопроса); Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда ВремяНачала = Неопределено; Если ДополнительныеПараметры.Свойство("ВремяНачала", ВремяНачала) Тогда ЗатраченноеВремя = ТекущаяДата() - ВремяНачала; ТекстСообщения = СтрШаблон("Затраченное время: %1 %2", ЗатраченноеВремя, "с"); Сообщить(ТекстСообщения); КонецЕсли; КонецЕсли; КонецПроцедуры
Выделим важные моменты в этом коде:
- Используется асинхронный метод ПоказатьВопрос. В нем первым параметром передается описание оповещения. Оно сообщает системе, что после того, как пользователь ответит на вопрос, нужно вызвать метод ПоказатьВопросЗавершение, расположенный в модуле этой же формы, и передать в него ДопПараметры.
- Методы обратного вызова могут располагаться в модуле формы, общем модуле или в модуле команды. Расположение метода указывается вторым параметром в конструкторе объекта ОписаниеОповещения.
- Метод ПоказатьВопросЗавершение обязательно должен быть экспортным, даже если он располагается в модуле той же формы. Если не указать ключевое слово Экспорт, то будет выдана ошибка:
- Поскольку метод ПоказатьВопрос – асинхронный, после вызова этого метода управление вернется к коду, вызвавшему его, не дожидаясь, когда асинхронный метод завершит свою работу. Поэтому сообщение о начале загрузки появится до того, как пользователь ответит на вопрос. В этом заключается важное отличие асинхронного метода от синхронного. Синхронный метод Вопрос блокирует поток выполнения команд, поэтому следующая команда может быть выполнена только после того, как пользователь ответит на вопрос.
- Если нужно выполнять какие-то действия после того, как пользователь ответит на вопрос, то эти действия нужно выполнять в методе ПоказатьВопросЗавершение, а не сразу после вызова метода ПоказатьВопрос. Это также связано с тем, что метод ПоказатьВопрос является асинхронным.
- После ответа пользователя на вопрос будет вызвана отдельная процедура. Может потребоваться передать в нее какие-то данные, необходимые для дальнейшей работы. Для этого можно использовать ДополнительныеПараметры – второй параметр метода ПоказатьВопросЗавершение. В нашем примере нужно знать время начала, когда пользователю был показан вопрос. Поэтому время начала передается в метод обратного вызова через ДополнительныеПараметры.
Обратите внимание, что имена асинхронных процедур, которые используют методы обратного вызова, начинаются со слов Начать или Показать. Приведем в таблице несколько примеров – имя синхронного метода и соответствующего ему асинхронного:
Синхронный метод | Асинхронный метод |
Вопрос | ПоказатьВопрос |
Предупреждение | ПоказатьПредупреждение |
ОткрытьЗначение | ПоказатьЗначение |
КопироватьФайл | НачатьКопированиеФайла |
ВвестиЧисло | ПоказатьВводЧисла |
НайтиФайлы | НачатьПоискФайлов |
ПолучитьФайл | НачатьПолучениеФайлаССервера |
Пример 2 – Сохранение файла на клиентском компьютере
Рассмотрим более сложный пример.
По данным информационной базы нужно сформировать файл с расширением xlsx, затем сохранить его на компьютере пользователя. Пользователь в диалоге сохранения файла должен указать имя файла и каталог для его сохранения.
Для реализации такого функционала можно использовать следующий код в модуле формы:
&НаКлиенте Процедура СохранитьФайлНаКлиенте(Команда) //1. Формирование файла на сервере, помещение во временное хранилище АдресФайлаВоВременномХранилище = СформироватьФайлНаСервере(); Если НЕ ЭтоАдресВременногоХранилища(АдресФайлаВоВременномХранилище) Тогда Возврат; КонецЕсли; //2. Открытие диалога сохранения файла Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение); Диалог.Заголовок = "Выберите файл для сохранения"; Диалог.МножественныйВыбор = Ложь; Диалог.Фильтр = "Документы Excel|*.xlsx|Все файлы|*.*"; ДопПараметры = Новый Структура("АдресФайлаВоВременномХранилище", АдресФайлаВоВременномХранилище); ОписаниеОповещения = Новый ОписаниеОповещения("ОповещениеПослеВыбораФайлаДляЗаписи", ЭтотОбъект, ДопПараметры); Диалог.Показать(ОписаниеОповещения); КонецПроцедуры &НаСервере Функция СформироватьФайлНаСервере() ИмяФайла = ПолучитьИмяВременногоФайла("xlsx"); //Формирование файла, заполнение его данными Макет = РеквизитФормыВЗначение("Объект").ПолучитьМакет("Макет"); ОбластьШапка = Макет.ПолучитьОбласть("Шапка"); ТабличныйДокумент = Новый ТабличныйДокумент; ТабличныйДокумент.Вывести(ОбластьШапка); //Заполнение табличного документа //... ТабличныйДокумент.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX); ДвоичныеДанные = Новый ДвоичныеДанные(ИмяФайла); Попытка УдалитьФайлы(ИмяФайла); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтотОбъект.УникальныйИдентификатор); КонецФункции &НаКлиенте Процедура ОповещениеПослеВыбораФайлаДляЗаписи(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт //3. Получение данных из временного хранилища, сохранение с выбранным именем Если ТипЗнч(ВыбранныеФайлы) = Тип("Массив") Тогда Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда АдресФайлаВоВременномХранилище = Неопределено; Если ДополнительныеПараметры.Свойство("АдресФайлаВоВременномХранилище", АдресФайлаВоВременномХранилище) Тогда ОписаниеОповещения = Новый ОписаниеОповещения("ОповещениеПослеПолученияФайла", ЭтотОбъект); НачатьПолучениеФайлаССервера(ОписаниеОповещения, АдресФайлаВоВременномХранилище, ВыбранныеФайлы[0]); КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры &НаКлиенте Процедура ОповещениеПослеПолученияФайла(ПолученныйФайл, ДополнительныеПараметры) Экспорт //4. Уведомление пользователя о сохраненном файле Состояние("Записан файл " + ПолученныйФайл.ПолноеИмя); КонецПроцедуры
Разберем подробнее основные моменты в приведенном программном коде:
- На сервере в каталоге временных файлов создаем файл с уникальным именем и расширением xlsx. Заполняем его данными и помещаем во временное хранилище. Адрес во временном хранилище передаем на клиент, чтобы была возможность доступа к этим данным из клиентских процедур.
- Открываем диалог сохранения файла. Устанавливаем фильтр для диалога, чтобы пользователь мог сохранить файл с правильным расширением. Для отображения диалога используется асинхронный метод Показать, которому в параметре передается описание оповещения. Оно указывает системе, что после выбора пользователем имени файла будет вызвана процедура ОповещениеПослеВыбораФайлаДляЗаписи из модуля этой же формы, в эту процедуру будет передан адрес во временном хранилище, где располагаются данные требуемого файла.
- Вызывается метод НачатьПолучениеФайлаССервера – инициируется получение файла с сервера и сохранение его на клиентском компьютере под указанным пользователем именем. В качестве параметра передается еще одно описание оповещения. Оно указывает, что после завершения получения файла с сервера будет вызвана процедура ОповещениеПослеПолученияФайла.
- После того, как загрузка файла с сервера на клиентский компьютер закончена, система уведомляет пользователя, что загрузка файла завершена.
Схематично изобразим последовательность вызовов методов из приведенного фрагмента кода:
Вложенные процедуры с асинхронными методами
В предыдущих примерах описание оповещения передавалось в качестве параметра в асинхронный метод. Когда асинхронный метод завершал свою работу (пользователь ответил на вопрос, файл с сервера был сохранен на клиентский компьютер и т.д.), платформа вызывала метод, указанный в описании оповещения. Явного вызова обработчиков оповещений из программного кода не происходило.
Во встроенном языке есть метод ВыполнитьОбработкуОповещения, который используется для того, чтобы явно выполнить метод обратного вызова, указанный в качестве параметра. Такое действие может потребоваться в сложных случаях, когда асинхронные методы “вложены” друг в друга, и после цепочки асинхронных вызовов нужно выполнить действие, определенное раньше, еще до начала этих асинхронных вызовов.
В качестве примера рассмотрим следующую задачу. Необходимо открыть форму для выгрузки данных во внешнюю систему. Выгрузку можно производить только в том случае, когда в константе Лицензия заполнены данные лицензии для выгрузки. Если лицензия не заполнена, нужно предложить пользователю ввести данные лицензии, сохранить их в константе, после чего открыть форму для выгрузки данных во внешнюю систему.
Для начала рассмотрим синхронный код, решающий поставленную задачу:
&НаКлиенте Процедура ОтправитьВоВнешнююСистему(Команда) ДанныеДляВнешнейСистемы = Новый Структура; ДанныеДляВнешнейСистемы.Вставить("Дата", ТекущаяДата()); ДанныеДляВнешнейСистемы.Вставить("Описание", "ОписаниеПлатежа"); //... Если ПроверитьЛицензию() Тогда //Открыть форму подключения к внешней системе ОткрытьФорму("Обработка.ПодключениеКВнешнейСистеме.Форма", ДанныеДляВнешнейСистемы); Иначе ТекстВопроса = "Для подключения к внешней системе необходимо указать данные лицензии. |Ввести сейчас?"; Ответ = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет); Если Ответ = КодВозвратаДиалога.Да Тогда Лицензия = ""; ВвестиСтроку(Лицензия, "Лицензия"); Если НЕ ПустаяСтрока(Лицензия) Тогда СохранитьЛицензию(Лицензия); //Открыть форму подключения к внешней системе ОткрытьФорму("Обработка.ПодключениеКВнешнейСистеме.Форма", ДанныеДляВнешнейСистемы); КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры &НаСервереБезКонтекста Функция ПроверитьЛицензию() Лицензия = Константы.Лицензия.Получить(); Возврат ЗначениеЗаполнено(Лицензия); КонецФункции &НаСервереБезКонтекста Процедура СохранитьЛицензию(Лицензия) Константы.Лицензия.Установить(Лицензия); КонецПроцедуры
Синхронный программный код достаточно компактный, легко читается, удобен для анализа. В нем встречаются методы Вопрос и ВвестиСтроку. Нужно заменить их на асинхронные аналоги ПоказатьВопрос и ПоказатьВводСтроки, создать описания оповещений и разделить код на отдельные процедуры, поскольку после вызова асинхронного метода управление вернется к коду, вызвавшему его, не дожидаясь, когда асинхронный метод завершит свою работу.
Получится следующий асинхронный код:
&НаКлиенте Процедура ОтправитьВоВнешнююСистему(Команда) ДанныеДляВнешнейСистемы = Новый Структура; ДанныеДляВнешнейСистемы.Вставить("Дата", ТекущаяДата()); ДанныеДляВнешнейСистемы.Вставить("Описание", "ОписаниеПлатежа"); //... ОбработкаПродолжения = Новый ОписаниеОповещения("ОтправитьВоВнешнююСистемуПродолжение", ЭтотОбъект, ДанныеДляВнешнейСистемы); НачатьПроверкуЛицензииИПодключениеКВнешнейСистеме(ОбработкаПродолжения); КонецПроцедуры &НаКлиенте Процедура НачатьПроверкуЛицензииИПодключениеКВнешнейСистеме(ОбработкаПродолжения) Экспорт Если ПроверитьЛицензию() Тогда ВыполнитьОбработкуОповещения(ОбработкаПродолжения, Истина); Иначе ПоказатьВопросВводаЛицензии(ОбработкаПродолжения); КонецЕсли; КонецПроцедуры &НаСервереБезКонтекста Функция ПроверитьЛицензию() Лицензия = Константы.Лицензия.Получить(); Возврат ЗначениеЗаполнено(Лицензия); КонецФункции &НаКлиенте Процедура ПоказатьВопросВводаЛицензии(ОбработкаЗавершения) ПараметрыЗавершения = Новый Структура; ПараметрыЗавершения.Вставить("ОбработкаЗавершения", ОбработкаЗавершения); ОбработкаОтвета = Новый ОписаниеОповещения("ПоказатьВопросВводаЛицензииЗавершение", ЭтотОбъект, ПараметрыЗавершения); ТекстВопроса = "Для подключения к внешней системе необходимо указать данные лицензии. |Ввести сейчас?"; ПоказатьВопрос(ОбработкаОтвета, ТекстВопроса, РежимДиалогаВопрос.ДаНет); КонецПроцедуры &НаКлиенте Процедура ПоказатьВопросВводаЛицензииЗавершение(Ответ, Параметры) Экспорт Если Ответ = КодВозвратаДиалога.Да Тогда ОбработкаПодключения = Новый ОписаниеОповещения("ВводЛицензииЗавершение", ЭтотОбъект, Параметры); ПоказатьВводСтроки(ОбработкаПодключения, "", "Лицензия"); Иначе ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения, Ложь); КонецЕсли; КонецПроцедуры &НаКлиенте Процедура ВводЛицензииЗавершение(ВведеннаяСтрока, Параметры) Экспорт Если ПустаяСтрока(ВведеннаяСтрока) Тогда ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения, Ложь); Иначе СохранитьЛицензию(ВведеннаяСтрока); ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения, Истина); КонецЕсли; КонецПроцедуры &НаСервереБезКонтекста Процедура СохранитьЛицензию(Лицензия) Константы.Лицензия.Установить(Лицензия); КонецПроцедуры &НаКлиенте Процедура ОтправитьВоВнешнююСистемуПродолжение(ЕстьЛицензия, ДанныеДляВнешнейСистемы) Экспорт Если НЕ ЕстьЛицензия Тогда Возврат; КонецЕсли; //Открыть форму подключения к внешней системе ОткрытьФорму("Обработка.ПодключениеКВнешнейСистеме.Форма", ДанныеДляВнешнейСистемы); КонецПроцедуры
Обратите внимание на использование метода ВыполнитьОбработкуОповещения. Описание оповещения создается в самой первой процедуре – ОтправитьВоВнешнююСистему. В нем указывается, что должна быть вызвана процедура ОтправитьВоВнешнююСистемуПродолжение, в которую следует передать в качестве параметра данные для выгрузки во внешнюю систему. Но вызов этой процедуре происходит не в момент создания описания оповещения, а позднее, в других процедурах – после проверки заполненности лицензии или после того, как пользователь введет номер лицензии.
Получается, что из-за асинхронности код состоит из логически взаимосвязанных отдельных процедур. Переход к открытию формы подключения к внешней системы может производиться из разных точек алгоритма. Поэтому в этих точках нужно знать данные для выгрузки во внешнюю систему и результат проверки лицензии.
Вспомним, что в асинхронных процедурах есть параметр с именем ДополнительныеПараметры, при помощи которого в метод обратного вызова можно передать произвольные данные. Этот параметр и используется в приведенном алгоритме. С его помощью организуется передача данных между вызываемыми друг за другом асинхронными методами. В этом параметре передаются данные для выгрузки и указывается метод, который нужно вызвать для открытия формы подключения к внешней системе. Для явного вызова этого метода и используется процедура ВыполнитьОбработкуОповещения.
Из приведенного кода видно, что использование методов обратного вызова усложняет разработку. Рассмотрим, какие сложности встречаются при написании асинхронного кода и какие способы упрощения может предложить платформа “1С:Предприятие”.
Сложности при использовании методов обратного вызова
В языках программирования, в которых можно передавать функцию как параметр другой процедуры, например, в JavaScript, есть такой термин, как callback hell (англ. – ад обратных вызовов) – многократно вложенные друг в друга блоки. В качестве примера можно привести следующий код:
function callbackHell(){ step1(function() { step2(function() { step3(function() { step4(function() { step5(function() { //... }); }); }); }); }); }
Подобные конструкции делают код сложным для чтения, анализа и поддержки.
Во встроенном языке нет возможности указать функцию в качестве параметра другого метода, поэтому не удастся создать точно такой же код. Но использование методов обратного вызова усложняет код, делает его фрагментированным. Получается своего рода аналог callback hell для встроенного языка “1С:Предприятие”.
Вспомним для примера код, передающий файл с сервера на клиентский компьютер. Обратите внимание, что линейный по своей логике код (без условных операторов и циклов) оказывается разделенным на отдельные фрагменты только из-за того, что используются асинхронные процедуры с методами обратного вызова. Это усложняет разработку кода.
Также сложно разобраться в сильно фрагментированном коде (особенно в типовых конфигурациях), поскольку отдельная процедура сама по себе не дает полного представления, что именно делает программный код. Нужно обязательно отследить всю цепочку процедур, выяснить взаимосвязи между процедурами, только тогда можно разобраться, как работает этот код.
В качестве примера можно проанализировать код типовой конфигурации 1С:Розница, который выполняет закрытие кассовой смены. Этот процесс достаточно сложный, включает в себя несколько этапов:
- Выбрать кассу, по которой нужно произвести закрытие
- Подтвердить закрытие смены
- Проверить наличие непробитых чеков
- Запросить сумму выемки денежных средств
- Выполнить сверку итогов по картам на эквайринговом терминале
- Заархивировать чеки за текущую смену, сформировать отчет о розничных продажах
- Создать документ выемки денежных средств, отправить команду выемки на ККТ
- Сформировать Z-отчет на ККТ
- Проверить наличие ошибок ККТ при формировании Z-отчета
- Зафиксировать время закрытия кассовой смены в базе
- Передать документы в ЕГАИС
- Открыть формы сформированных документов
- Вывести сообщение с итоговой информацией о продажах и возвратах
Как видно, этапов достаточно много. К тому же периодически нужно задавать уточняющие вопросы, открывать дополнительные формы, обрабатывать возникающие ошибки. Поэтому цепочка методов получается сложная, приходится разбираться в похожих процедурах, вроде ПродолжитьЗакрытиеСменыОкончание, ПродолжитьЗакрытиеСменыОкончаниеФискальныйОтчетЗавершение и т.д.
Подобный код со своими нюансами есть во многих типовых конфигурациях – УТ, БП и т.д. За счет наличия в коде асинхронных методов код типовых конфигураций усложнился – его тяжелее и создавать, и отлаживать.
Поэтому в следующей главе рассмотрим инструменты платформы для упрощения написания кода.
Инструменты рефакторинга
В конфигураторе есть набор инструментов, которые призваны упростить работу с асинхронными методами. Команды доступны в меню конфигуратора Текст – Рефакторинг, а также в контекстном меню текстового редактора в подменю Рефакторинг:
Рассмотрим их подробнее.
Создать обработку оповещения
При создании описания метода обратного вызова нужно корректно указать все параметры этого метода. Конечно, можно посмотреть их в Синтакс-помощнике и вручную составить описание метода, но быстрее и удобнее будет, если платформа сама сгенерирует такой метод. И такая возможность есть.
Если установить курсор на имени асинхронного метода, после которого следует открывающаяся скобка, например, ПоказатьВопрос, НачатьПеремещениеФайла и т.д., то в меню станет доступна команда Создать обработку оповещения, которая самостоятельно сформирует описание оповещения и метод обратного вызова.
Рассмотрим пример. Есть фрагмент кода, в котором для метода ПоказатьВопрос не указан первый параметр – обработка оповещения:
&НаКлиенте Процедура ЗагрузитьДанные() ПоказатьВопрос(, "Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); КонецПроцедуры
Установим курсор на метод ПоказатьВопрос и вызовем команду Создать обработку оповещения. Получим следующий код:
&НаКлиенте Процедура ЗагрузитьДанные() ПоказатьВопрос(Новый ОписаниеОповещения("ЗагрузитьДанныеЗавершение", ЭтаФорма), "Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); КонецПроцедуры &НаКлиенте Процедура ЗагрузитьДанныеЗавершение(РезультатВопроса, ДополнительныеПараметры) Экспорт КонецПроцедуры
Это очень удобный инструмент, который ускоряет создание кода, поскольку теперь не требуется искать в Синтакс-помощнике описание параметров метода обратного вызова и создавать сам метод вручную.
Преобразовать вызов
Этот инструмент рефакторинга помогает преобразовать код, содержащий синхронный метод, в код с использованием соответствующего асинхронного метода. Также при этом создается описание оповещение и метод обратного вызова.
Рассмотрим пример. Есть фрагмент кода:
&НаКлиенте Процедура ЗагрузитьДанные() Ответ = Вопрос("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); Если Ответ = КодВозвратаДиалога.Да Тогда //Логика загрузки КонецЕсли; КонецПроцедуры
Установим курсор на метод Вопрос и вызовем команду Преобразовать вызов. Получим следующий код с использованием асинхронного метода ПоказатьВопрос:
&НаКлиенте Процедура ЗагрузитьДанные() Ответ = Неопределено; ПоказатьВопрос(Новый ОписаниеОповещения("ЗагрузитьДанныеЗавершение", ЭтаФорма), "Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); КонецПроцедуры &НаКлиенте Процедура ЗагрузитьДанныеЗавершение(РезультатВопроса, ДополнительныеПараметры) Экспорт Ответ = РезультатВопроса; Если Ответ = КодВозвратаДиалога.Да Тогда //Логика загрузки КонецЕсли; КонецПроцедуры
Этот инструмент позволяет переписать код с устаревшими синхронными методами, помогает автоматически заменить их на соответствующие асинхронные методы. Конечно, любой сформированный автоматически код обязательно нужно проверять, чтобы при рефакторинге не потерялась логика.
Найти вызовы модуля
Команда Преобразовать вызов работает только с одним участком кода. Часто требуется проанализировать целый модуль, найти в нем “нерекомендуемые синхронные методы”, чтобы заменить их на асинхронные аналоги. Для этого существует команда Найти вызовы модуля. Найденные строки кода, содержащие “нерекомендуемые синхронные вызовы”, выводятся в окно с результатами поиска:
Анализ нерекомендуемых синхронных вызовов конфигурации
Команда Найти вызовы модуля ищет синхронные методы только в одном модуле. Если нужно проанализировать такие вызовы во всей конфигурации, то можно воспользоваться командой в меню Конфигурация – Рефакторинг – Анализ нерекомендуемых синхронных вызовов конфигурации:
Этот инструмент умеет не только находить синхронные вызовы во всех модулях конфигурации, но и выполнять автоматическую замену на соответствующие асинхронные методы в простых случаях. Также есть возможность создавать заготовки для методов обратного вызова.
Таким образом, фирма “1С” не “спрятала” асинхронность от программистов на уровне платформы. Нужно разобраться с этой функциональностью. Для реализации асинхронности с использованием методов обратного вызова следует применять асинхронные методы (вместо Вопрос – ПоказатьВопрос, вместо Предупреждение – ПоказатьПредупреждение и т.д.). Если же в существующем коде встречаются синхронные вызовы, его нужно переработать – заменить синхронные методы на соответствующие им асинхронные. Для упрощения разработки можно использовать рассмотренные инструменты конфигуратора по рефакторингу кода.
В следующей главе рассмотрим новый вариант реализации асинхронности, который появился в платформе 8.3.18. Это асинхронность с использованием обещаний.
Использование обещаний
Использование методов обратного вызова усложняет программный код, делает его фрагментированным, сложным для восприятия и доработки. Синхронный код, в котором выполняемые команды расположены последовательно, друг за другом, создается и анализируется гораздо проще. Но для работы в веб-клиенте требуется именно асинхронный принцип выполнения операций. Как разрешить это противоречие – упростить написание кода и выполнить требования, предъявляемые браузерами?
В других языках программирования, таких как JavaScript или Python, существует тип данных Promise (англ. – обещание) и ключевые слова async/await. Использование этих конструкций делает асинхронный код простым, читаемым и удобным для доработки.
Похожий подход был реализован фирмой “1С” в платформе 8.3.18. Причем новый функционал не завязан на режим совместимости конфигурации, т.е. режим совместимости может быть установлен, например, в значение Версия 8.3.6, но при использовании платформы 8.3.18 и новее возможно использовать функционал асинхронности через обещания.
Важно отметить, что сам принцип использования асинхронности в платформе остался прежним. По-прежнему асинхронность доступна для работы с блокирующими окнами, файлами и каталогами, механизмами криптографии и внешними компонентами. Изменился только “внешний вид” программного кода, другими словами – способ указания платформе, какой именно код нужно выполнить после завершения асинхронного метода. Главная задача нововведения – приблизить асинхронный код к обычному последовательному коду, уменьшить сложность разработки.
Рассмотрим далее подробнее новые возможности платформы.
Новый тип – Обещание
В платформе 8.3.18 появился новый тип данных – Обещание. Объект такого типа предназначен для организации асинхронного кода.
Обещание представляет собой “хранилище” для пока что еще неизвестного результата выполнения некоторого действия (асинхронной функции).
Почему используется термин Обещание? Вспомним, что при вызове асинхронного метода поток выполнения не прерывается, управление возвращается к коду, вызвавшему этот метод. Но на выполнение самого асинхронного метода требуется время (пока пользователь ответит на вопрос или пока файл будет передан с сервера на клиент). Во время выполнения асинхронного метода нельзя сказать, какой результат он вернул, поскольку метод еще не завершился. Как только асинхронный метод завершится, он уведомит о своем выполнении и предоставит доступ к результату своей работы.
Получается, что при вызове асинхронной функции она должна сразу вернуть управление вызвавшему ее коду, не блокируя поток выполнения. Значит, она должна вернуть какое-то значение. Но какое? Ведь на выполнение функции потребуется время, а результат выполнения еще неизвестен в данный момент. Значит, асинхронная функция не может сразу вернуть результат выполнения, но может “пообещать” вернуть его в указанную переменную, как только функция завершит работу. В этом и заключается смысл использования Обещаний.
Поэтому асинхронная функция во встроенном языке всегда возвращает значение типа Обещание, которое может находиться в одном из трех состояний:
- Ожидание (Pending) – начальное состояние. Асинхронная функция еще не завершила свое выполнение, результат еще неизвестен.
- Завершено успешно (Success/Fulfilled). Асинхронная функция отработала успешно. В таком случае Обещание содержит результат выполнения асинхронной функции.
- Завершено с ошибкой (Failure/Rejected). При выполнении асинхронной функции было вызвано исключение, не обработанное программно. В таком случае Обещание содержит исключение.
Таким образом, Обещание из начального состояния может перейти в одно из двух финальных состояний: или “Завершено успешно”, или “Завершено с ошибкой” в зависимости от результата работы асинхронной функции:
Фактически Обещание является заменой объекта ОписаниеОповещения. При использовании асинхронности с методами обратного вызова в этом объекте указывается, какую процедуру нужно выполнить после завершения асинхронного метода. Результат выполнения асинхронного метода будет содержаться в параметре метода обратного вызова. При использовании асинхронности через обещания результат асинхронной функции будет содержаться именно в объекте типа Обещание.
Объект типа Обещание доступен только в клиентском контексте: в тонком, толстом, мобильном клиентах и в веб-клиенте. На сервере этот объект недоступен. Это связано с тем, что асинхронные методы во встроенном языке создавались для использования только на клиенте.
Объект Обещание не имеет конструкторов, методов и свойств. Объект такого типа можно получить во встроенном языке только в качестве результата вызова асинхронной функции. Далее Обещание можно использовать в качестве аргумента оператора Ждать, чтобы получить результат выполнения асинхронной функции. Примеры программного кода будут рассмотрены далее. Других сценариев использования объекта Обещание не предусмотрено.
Асинхронные функции
Ранее отмечалось, что изначально во встроенном языке присутствовали только синхронные методы, которые блокируют поток выполнения команд.
Затем появились асинхронные процедуры, которые используют методы обратного вызова. Имена таких процедур начинаются со слов Начать или Показать, а в качестве параметра в процедуру передается ОписаниеОповещения. После завершения асинхронной процедуры производится вызов метода, указанного в объекте ОписаниеОповещения.
В платформе 8.3.18 появились новые асинхронные функции, возвращающие Обещание. Имена таких функций заканчиваются на Асинх.
Приведем в таблице несколько примеров – имя синхронного метода, соответствующую ему асинхронную процедуру и новую асинхронную функцию:
Синхронный метод | Асинхронная процедура, использующая метод обратного вызова | Асинхронная функция, возвращающая Обещание |
Вопрос | ПоказатьВопрос | ВопросАсинх |
Предупреждение | ПоказатьПредупреждение | ПредупреждениеАсинх |
ОткрытьЗначение | ПоказатьЗначение | ОткрытьЗначениеАсинх |
КопироватьФайл | НачатьКопированиеФайла | КопироватьФайлАсинх |
ВвестиЧисло | ПоказатьВводЧисла | ВвестиЧислоАсинх |
НайтиФайлы | НачатьПоискФайлов | НайтиФайлыАсинх |
ПолучитьФайл | НачатьПолучениеФайлаССервера | ПолучитьФайлССервераАсинх |
При помощи Синтакс-помощника для синхронного метода можно найти соответствующие ему асинхронные методы:
Сравним, например, методы для отображения вопроса пользователю. Отметим их сходства и отличия.
Синтаксис этих методов выглядит следующим образом:
Вопрос(<ТекстВопроса>, <Кнопки>, <Таймаут>, <КнопкаПоУмолчанию>, <Заголовок>, <КнопкаТаймаута>) ПоказатьВопрос(<ОписаниеОповещенияОЗавершении>, <ТекстВопроса>, <Кнопки>, <Таймаут>, <КнопкаПоУмолчанию>, <Заголовок>, <КнопкаТаймаута>) ВопросАсинх(<ТекстВопроса>, <Кнопки>, <Таймаут>, <КнопкаПоУмолчанию>, <Заголовок>, <КнопкаТаймаута>)
Вопрос и ВопросАсинх являются функциями.
ПоказатьВопрос – это процедура. Первым параметром передается объект ОписаниеОповещения, который указывает, какой именно метод должен быть вызван после того, как пользователь ответит на вопрос или откажется от ответа.
Новая функция ВопросАсинх, появившаяся в платформе 8.3.18, возвращает объект типа Обещание. Перечень параметров у этой функции такой же, как и у синхронного метода Вопрос.
Процедура ПоказатьВопрос и функция ВопросАсинх выполняются асинхронно. Ответ пользователя при использовании процедуры ПоказатьВопрос будет передан в первом параметре метода обратного вызова. При использовании функции ВопросАсинх тот же ответ пользователя будет содержаться в объекте типа Обещание.
Отметим, что не для всех синхронных методов реализованы аналогичные функции с модификатором Асинх. Например, для метода формы ОткрытьМодально соответствующая асинхронная функция не существует. Поэтому следует использовать процедуру ОткрытьФорму с указанием обработчика оповещения:
&НаКлиенте Процедура ВыбратьНоменклатуру(Команда) ОписаниеОповещения = Новый ОписаниеОповещения("ОткрытиеФормыЗавершение", ЭтотОбъект); ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", , , , , , ОписаниеОповещения, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца); КонецПроцедуры &НаКлиенте Процедура ОткрытиеФормыЗавершение(РезультатЗакрытия, ДополнительныеПараметры) Экспорт //Обработка результата... КонецПроцедуры
Работа с асинхронными функциями
Асинхронная функция возвращает значение типа Обещание. Чтобы из этого значения получить результат работы асинхронной функции, нужно воспользоваться оператором Ждать, который также появился в платформе 8.3.18. Единственным параметром оператора Ждать является объект типа Обещание:
Результат = Ждать Обещание;
Оператор Ждать выполняет ожидание завершения работы вызванной асинхронной функции, которая вернула Обещание, переданное как параметр оператора Ждать. Если асинхронная функция отработала штатно (Обещание находится в состоянии “Завершено успешно”), то результатом оператора Ждать является результат асинхронной функции. Если же асинхронная функция вызвала исключение, которое не было обработано в программном коде (Обещание находится в состоянии “Завершено с ошибкой”), оператор Ждать вызовет исключение.
В коде может встретиться вот такая строка:
Ждать 1000;
Что она означает? Может показаться, что это способ организации паузы во встроенном языке, а 1000 – это длительность ожидания в миллисекундах. Но на самом деле это совсем не так. Если параметром оператора Ждать является любое значение, кроме Обещания, то платформа создаст Обещание, в котором будет “спрятано” указанное значение (в данном случае – число 1000). Затем созданное Обещание будет передано как параметр оператора Ждать. Результатом такого оператора является число 1000, но этот результат не присваивается другой переменной, поэтому в строке кода опущен оператор присваивания:
Результат = Ждать 1000;
Так что указанная строка – это синтаксически корректный программный код, но не способ организации паузы.
Модификатор Асинх
Имена асинхронных функций платформы, возвращающих Обещание, заканчиваются на Асинх. Если разработчику нужно реализовать собственную процедуру или функцию, которая будет работать асинхронно, ее нужно описать с использованием модификатора Асинх:
&НаКлиенте Асинх Процедура ИмяПроцедуры() КонецПроцедуры &НаКлиенте Асинх Функция ИмяФункции() КонецФункции
Выделим несколько принципиально важных особенностей процедур или функций с модификатором Асинх.
Только внутри процедур или функций с модификатором Асинх можно использовать оператор Ждать. Также важно, что модификатор Асинх можно использовать только для клиентских процедур и функций. Если внутри обработчика клиентского события планируется использовать оператор Ждать, то такой обработчик также нужно описать с модификатором Асинх.
В процедурах и функциях с модификатором Асинх параметры всегда передаются по значению. При этом неважно, будет ли в описании метода использоваться ключевое слово Знач перед параметром или нет. Поэтому два указанных ниже описания асинхронных процедур являются абсолютно одинаковыми, параметр будет передан по значению:
Асинх Процедура ЗадатьВопрос(Знач РежимДиалога) Асинх Процедура ЗадатьВопрос(РежимДиалога)
Функция с модификатором Асинх всегда возвращает Обещание. Но по правилам встроенного языка функция должна возвращать то значение, которое разработчик указывает в качестве параметра оператора Возврат. Функция без модификатора Асинх именно так и делает – возвращает значение параметра оператора Возврат. Функция с модификатором Асинх возвращает Обещание. Если такая функция завершится успешно, без генерации исключения, то в Обещании будет “спрятано” возвращаемое значение. Чтобы из Обещания получить конкретное значение, нужно воспользоваться оператором Ждать:
&НаКлиенте Асинх Процедура ВывестиДанныеИзВнешнейСистемы(Команда) Результат = Ждать ПолучитьЗначениеИзВнешнейСистемы(); КонецПроцедуры &НаКлиенте Асинх Функция ПолучитьЗначениеИзВнешнейСистемы() //Здесь должен располагаться программный код для получения данных... Возврат Значение; КонецФункции
Если функция с модификатором Асинх во время своего выполнения вызвала исключение, то в Обещании будет “спрятано” это исключение.
Поговорим про перехват исключений подробнее, здесь тоже есть несколько важных нюансов.
Обработка исключений в асинхронных процедурах и функциях
Исключение, возникшее в процедуре или функции с модификатором Асинх, не отобразится пользователю. Например, вот в таком программном коде:
&НаКлиенте Процедура ВывестиДанныеИзВнешнейСистемы(Команда) ПолучитьЗначениеИзВнешнейСистемы(); КонецПроцедуры &НаКлиенте Асинх Функция ПолучитьЗначениеИзВнешнейСистемы() Возврат 5/0;//деление на ноль КонецФункции
Аналогично в таком коде выполнение никогда не попадет в секцию Исключение, именно потому что функция ПолучитьЗначениеИзВнешнейСистемы является асинхронной. Исключение, вызванное в такой функции, не возникнет в вызывающем коде:
&НаКлиенте Процедура ВывестиДанныеИзВнешнейСистемы(Команда) Попытка ПолучитьЗначениеИзВнешнейСистемы(); Исключение Сообщить(ОписаниеОшибки());//в эту строку не попадем КонецПопытки; КонецПроцедуры &НаКлиенте Асинх Функция ПолучитьЗначениеИзВнешнейСистемы() Возврат 5/0;//деление на ноль КонецФункции
Чтобы в вызывающем коде обработать исключение, возникшее в функции с модификатором Асинх, нужно Обещание, возвращаемое такой функцией, использовать в операторе Ждать:
&НаКлиенте Асинх Процедура ВывестиДанныеИзВнешнейСистемы(Команда) Попытка Ждать ПолучитьЗначениеИзВнешнейСистемы(); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; КонецПроцедуры &НаКлиенте Асинх Функция ПолучитьЗначениеИзВнешнейСистемы() Возврат 5/0; КонецФункции
Любая процедура встроенного языка, в том числе процедура с модификатором Асинх, в отличие от функции, не возвращает значения. Поэтому процедура не может вернуть Обещание, следовательно, в коде, вызвавшем асинхронную процедуру, принципиально нельзя перехватить исключение, возникшее в асинхронной процедуре. Такое исключение будет сразу показано пользователю:
&НаКлиенте Процедура ВывестиДанныеИзВнешнейСистемы(Команда) Попытка ПолучитьЗначениеИзВнешнейСистемы(); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; КонецПроцедуры &НаКлиенте Асинх Процедура ПолучитьЗначениеИзВнешнейСистемы() А = 5/0; КонецПроцедуры
Поэтому процедуры с модификатором Асинх удобно использовать в качестве обработчиков клиентских событий формы, в которых нужно будет применять оператор Ждать. В остальных случаях удобнее будет воспользоваться асинхронными функциями, поскольку это позволит обрабатывать исключения.
Примеры использования асинхронных функций
Организация диалога с пользователем
Необходимо задать вопрос пользователю, на который он может ответить Да или Нет. После того, как пользователь ответит на вопрос, в сообщении выводим, сколько времени ему потребовалось на ответ.
Для решения поставленной задачи в модуле формы написан следующий код:
&НаКлиенте Асинх Процедура ЗадатьВопрос(Команда) ВремяНачала = ТекущаяДата(); Результат = Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); Сообщить("Начало загрузки"); ЗатраченноеВремя = ТекущаяДата() - ВремяНачала; ТекстСообщения = СтрШаблон("Затраченное время: %1 %2", ЗатраченноеВремя, "с"); Сообщить(ТекстСообщения); КонецПроцедуры
В коде используется асинхронная функция платформы ВопросАсинх, которая возвращает Обещание. Это Обещание указывается в качестве параметра оператора Ждать. Система ожидает реакции пользователя. Когда пользователь ответит на вопрос и Обещание “разрешится”, в переменную Результат будет помещен выбранный пользователем вариант ответа на вопрос (Да или Нет).
Эта же задача раньше была решена с использованием метода обратного вызова. В данном примере программный код получился более простым, причем он очень похож на код с использованием аналогичных синхронных методов.
Копирование файла
Необходимо скопировать файл с одного диска на другой. Для решения этой задачи в модуле формы используется следующий код:
&НаКлиенте Асинх Процедура СкопироватьФайл(Команда) Попытка Результат = Ждать КопироватьФайлАсинх("C:1.xlsx", "D:1.xlsx"); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; КонецПроцедуры
В этом фрагменте кода используется асинхронная функция платформы КопироватьФайлАсинх. Она также возвращает Обещание, поступающее в оператор Ждать в качестве параметра. Система дожидается, когда копирование файла будет завершено. Когда файл будет скопирован, Обещание будет “развернуто”, из него будет получена строка, содержащая полное имя скопированного файла. Эта строка будет помещена в переменную Результат.
Важный момент и отличие от предыдущего примера – асинхронная функция платформы КопироватьФайлАсинх может вызвать исключение в процессе своей работы, например, когда не был найден исходный файл, когда нет прав доступа для записи файла, когда недостаточно места на диске и т.д. В таком случае в Обещании, возвращаемом функцией КопироватьФайлАсинх, будет содержаться исключение. Чтобы перехватить это исключение и обработать его, используется конструкция Попытка.
Проверка возможности работы с внешней системой
Ранее рассматривалась задача проверки возможности выгрузки данных во внешнюю систему. Для ее решения был написан синхронный код, а также процедуры, использующие методы обратного вызова. Теперь решим эту же задачу с использованием функций, возвращающих Обещание.
Напомним, что выгрузку можно производить только в том случае, когда в константе Лицензия заполнены данные лицензии для выгрузки. Если лицензия не заполнена, нужно предложить пользователю ввести данные лицензии, сохранить их в константе, после чего открыть форму для выгрузки данных во внешнюю систему.
Программный код выглядит следующим образом:
&НаКлиенте Асинх Процедура ОтправитьВоВнешнююСистему(Команда) ДанныеДляВнешнейСистемы = Новый Структура; ДанныеДляВнешнейСистемы.Вставить("Дата", ТекущаяДата()); ДанныеДляВнешнейСистемы.Вставить("Описание", "ОписаниеПлатежа"); //... Если ПроверитьЛицензию() Тогда //Открыть форму подключения к внешней системе Иначе ТекстВопроса = "Для подключения к внешней системе необходимо указать данные лицензии. |Ввести сейчас?"; Ответ = Ждать ВопросАсинх(ТекстВопроса, РежимДиалогаВопрос.ДаНет); Если Ответ = КодВозвратаДиалога.Да Тогда Лицензия = ""; Лицензия = Ждать ВвестиСтрокуАсинх(Лицензия, "Лицензия"); Если НЕ ПустаяСтрока(Лицензия) Тогда СохранитьЛицензию(Лицензия); //Открыть форму подключения к внешней системе КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры &НаСервереБезКонтекста Функция ПроверитьЛицензию() Лицензия = Константы.Лицензия.Получить(); Возврат ЗначениеЗаполнено(Лицензия); КонецФункции &НаСервереБезКонтекста Процедура СохранитьЛицензию(Лицензия) Константы.Лицензия.Установить(Лицензия); КонецПроцедуры
В этом фрагменте кода используются асинхронные функции платформы ВопросАсинх и ВвестиСтрокуАсинх, которые возвращают Обещание. Логика работы с асинхронными функциями такая же, как и в двух предыдущих примерах, – Обещание передается в качестве параметра оператора Ждать, который ожидает выполнения асинхронных функций, после чего может быть получен доступ к результату их работы.
Отметим важное отличие приведенного кода от кода с использованием объектов типа ОписаниеОповещения. При использовании асинхронных функций, возвращающих Обещания, не нужно разрабатывать цепочку взаимосвязанных методов обратного вызова, организовывать передачу данных между ними. Код становится не таким фрагментированным.
Таким образом, использование асинхронных функций, возвращающих Обещания, упрощает работу разработчикам, код становится более понятным (похожим на код с использованием аналогичных синхронных методов), простым для анализа и модификации.
Вопрос пользователю во время закрытия формы
Перед закрытием формы или перед закрытием всего приложения нужно задать вопрос, действительно ли следует выполнить закрытие, чтобы пользователь не потерял несохраненные данные. Попробуем решить эту задачу с использованием асинхронных методов. В форме создадим обработчик события ПередЗакрытием:
&НаКлиенте Асинх Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка) Если ЗавершениеРаботы Тогда Отказ = Истина; ТекстПредупреждения = "Несохраненные данные будут потеряны. Закрыть форму?"; Иначе Ответ = Ждать ВопросАсинх("Закрыть форму без сохранения данных?", РежимДиалогаВопрос.ДаНет); Если Ответ = КодВозвратаДиалога.Нет Тогда Отказ = Истина; КонецЕсли; КонецЕсли; КонецПроцедуры
Начиная с платформы 8.3.8, нужно разделять два варианта закрытия:
- Форма закрывается при закрытии приложения в целом
- Пользователь закрывает конкретную форму
Поэтому в коде обрабатывается два этих варианта. При закрытии приложения в целом параметр ЗавершениеРаботы принимает значение Истина. Важно, что программно нельзя отменить закрытие приложения, можно только показать предупреждение пользователю. Для этого параметр Отказ устанавливается в значение Истина. В таком случае пользователю при закрытии будет показано предупреждение, которое передается в параметре ТекстПредупреждения.
При закрытии конкретной формы пользователю задается вопрос. Если пользователь отвечает, что не требуется закрывать форму, параметр Отказ устанавливается в значение Истина, форма не закрывается.
Но при проверке работоспособности этого кода в режиме “1С:Предприятие” обнаруживается неожиданное поведение. При закрытии приложения никакое предупреждение не отображается. При закрытии формы сначала форма закрывается, а только потом отображается вопрос. При любом ответе пользователя на вопрос ничего не происходит, потому что форма уже закрылась.
Почему система ведет себя таким образом?
При закрытии приложения в целом или конкретной формы платформа вызывает обработчик события формы ПередЗакрытием. В этом обработчике можно управлять поведением системы при помощи изменения значения параметров. В приведенном выше примере изменялись значения параметров Отказ и ТекстПредупреждения.
Вспомним, что в процедурах и функциях с модификатором Асинх параметры всегда передаются по значению. Поэтому изменения значений параметров, произведенные внутри асинхронной процедуры ПередЗакрытием, недоступны для кода, который вызвал эту процедуру. Поэтому “снаружи” этой процедуры параметр Отказ принимает значение Ложь. В таком случае при закрытии приложения предупреждение пользователю не выводится, приложение просто закрывается. Это и наблюдается в пользовательском режиме именно потому, что процедура ПередЗакрытием асинхронная:
Когда закрывается только одна форма, а не приложение в целом, в приведенном коде происходит вызов асинхронной функции ВопросАсинх. При этом выполнение процедуры ПередЗакрытием приостанавливается, управление возвращается к коду, вызвавшему этот метод. Поскольку процедуру ПередЗакрытием вызвала платформа, управление возвращается платформе. Параметр Отказ в коде не был изменен, кроме того любые изменения параметра в самой асинхронной процедуре “не видны” тому коду, который вызвал эту асинхронную процедуру, потому что параметры в нее передаются по значению. Значит, при возвращении управления платформе параметр Отказ принимает значение Ложь, поэтому форма закрывается. Вопрос пользователю отображается, но когда пользователь ответит на вопрос, форма уже закрыта, отменить ее закрытие невозможно.
Эта особенность асинхронных обработчиков событий может оказаться неожиданной. Поэтому если процедура – обработчик события должна через параметры передать какие-то данные вызывающему ее коду, нельзя описывать ее с модификатором Асинх из-за описанной выше особенности.
Вместо асинхронной функции в данном случае можно использовать метод обратного вызова:
&НаКлиенте Перем ЗакрытиеФормыРазрешено; &НаКлиенте Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка) Если ЗавершениеРаботы Тогда Отказ = Истина; ТекстПредупреждения = "Несохраненные данные будут потеряны. Закрыть форму?"; ИначеЕсли ЗакрытиеФормыРазрешено = Неопределено Тогда ОписаниеОповещения = Новый ОписаниеОповещения("ПередЗакрытиемЗавершение", ЭтотОбъект); ПоказатьВопрос(ОписаниеОповещения, "Закрыть форму без сохранения данных?", РежимДиалогаВопрос.ДаНет); Отказ = Истина; КонецЕсли; КонецПроцедуры &НаКлиенте Процедура ПередЗакрытиемЗавершение(РезультатВопроса, ДополнительныеПараметры) Экспорт Если РезультатВопроса = КодВозвратаДиалога.Да Тогда ЗакрытиеФормыРазрешено = Истина; Закрыть(); КонецЕсли; КонецПроцедуры
Ошибки при использовании асинхронных функций в коде
Разберем наиболее часто встречающиеся ошибки при использовании асинхронных функций в программном коде.
Ошибка 1 – Только клиентский контекст
Объявим асинхронную функцию с директивой компиляции НаСервере:
&НаСервере Асинх Функция ПроверитьНаСервере() //... Возврат РезультатПроверки; КонецФункции
При проверке синтаксиса модуля конфигуратор выдаст ошибку:
Недопустимое объявление асинхронной процедуры или функции
Ошибка возникла, потому что модификатор Асинх можно использовать только для клиентских процедур и функций. К тому же тип данных Обещание доступен только на клиенте. Поэтому для исправления ошибки нужно или убрать из описания функции модификатор Асинх, или использовать директиву компиляции НаКлиенте.
Ошибка 2 – Оператор Ждать только в асинхронных методах
Рассмотрим следующий пример. В клиентской процедуре задаем вопрос пользователю:
&НаКлиенте Процедура ЗадатьВопрос(Команда) Результат = Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); //... КонецПроцедуры
При проверке синтаксиса модуля конфигуратор выдает ошибку:
Оператор Ждать (Await) может употребляться только в асинхронных процедурах или функциях
Для исправления ошибки нужно воспользоваться модификатором Асинх для описания этой процедуры:
&НаКлиенте Асинх Процедура ЗадатьВопрос(Команда) Результат = Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); //... КонецПроцедуры
Ошибка 3 – Подходящие версии платформы
Еще один пример. Процедура выглядит синтаксически корректно:
&НаКлиенте Асинх Процедура ЗадатьВопрос(Команда) Результат = Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); //... КонецПроцедуры
Но проверка синтаксиса в конфигураторе выдает ошибки:
Ожидается определение процедуры/функции <<?>>Асинх Процедура ЗадатьВопрос(Команда) (Проверка: Тонкий клиент) Ожидается символ ';' Результат = Ждать<<?>> ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); (Проверка: Тонкий клиент)
Такая ошибка может возникать, если открыть данный программный код на платформе 8.3.17 или предыдущих, в которых еще не реализован функционал Обещаний. Обратите внимание, что в приведенном фрагменте кода не подсвечиваются красным ключевые слова Асинх и Ждать. Чтобы ошибка не возникала, нужно использовать платформу 8.3.18 или новее.
Принципы работы асинхронных функций
Разберем подробнее, как работают асинхронные функции, возвращающие значение типа Обещание.
Ранее отмечалось, что оператор Ждать выполняет ожидание завершения работы вызванной асинхронной функции, которая вернула Обещание, переданное как параметр оператора Ждать. Получается, что оператор Ждать блокирует поток выполнения команд, пока асинхронная функция не отработает? Как тогда такие функции могут использоваться в веб-клиенте?
Нет, блокировки потока не происходит. Асинхронность в платформе “1С:Предприятие” осталась такая же, как и при работе с методами обратного вызова. Изменился только подход к написанию кода.
С логической точки зрения оператор Ждать ожидает, пока завершится асинхронная функция. Технически при этом происходит приостановка выполнения текущего метода, управление возвращается к коду, вызвавшему текущий метод. Происходит выход из текущего выполняющегося метода, но при этом значения локальных переменных, использующихся в текущем методе, сохраняются. Это позволит в дальнейшем, после завершения работы асинхронной функции, вернуться к продолжению работы текущего метода.
Асинхронная функция работает, это занимает какое-то время, наконец она завершается. Оператор Ждать в зависимости от результата работы функции может вернуть значение или вызвать исключение. После этого происходит возобновление приостановленного метода, выполняется повторный вход в этот метод в ту строку, где была выполнена приостановка. Восстанавливаются значения локальных переменных, что позволяет дальше выполнять код метода с момента приостановки с тем же самым контекстом.
На примере продемонстрируем, что при выполнении оператора Ждать действительно происходит возврат к вызвавшему методу:
&НаКлиенте Асинх Процедура ВывестиОтветНаВопрос(Команда) Обещание = ОтветНаВопрос(); Сообщить("Пользователь выбрал вариант"); Сообщить(Ждать Обещание); КонецПроцедуры &НаКлиенте Асинх Функция ОтветНаВопрос() Возврат Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); КонецФункции
При выполнении данного кода в пользовательском режиме вывод сообщения “Пользователь выбрал вариант” произойдет раньше, чем пользователь ответит на вопрос. Хотя в коде строка с выводом сообщения следует после вызова функции, задающей вопрос пользователю. Это демонстрирует, что основной поток выполнения не был заблокирован во время ожидания реакции пользователя. Выполнение функции ОтветНаВопрос было приостановлено, управление вернулось к процедуре ВывестиОтветНаВопрос.
Проанализируем, как выполняется код асинхронной процедуры:
&НаКлиенте Асинх Процедура СкопироватьФайл(Команда) СкопированныйФайл = Ждать КопироватьФайлАсинх("C:1.xlsx", "D:1.xlsx"); Сообщить(СкопированныйФайл); КонецПроцедуры
В данном фрагменте кода приостановка выполнения происходит в операторе Ждать. Приостановка будет продолжаться до того момента, пока не разрешится Обещание, возвращаемое асинхронной функцией КопироватьФайлАсинх. Другими словами – до тех пор, пока файл не будет скопирован либо не возникнет исключение при выполнении функции. После разрешения Обещания происходит возобновление выполнения процедуры. Имя файла-получателя будет присвоено переменной СкопированныйФайл. После этого платформа может переходить к выполнению следующей строки кода, сообщить значение этой переменной пользователю.
Такое поведение платформы можно сравнить с использованием метода обратного вызова и провести аналогию. Код уже знаком нам:
&НаКлиенте Процедура СкопироватьФайл(Команда) ОписаниеОповещения = Новый ОписаниеОповещения("КопированиеФайлаЗавершение", ЭтотОбъект); НачатьКопированиеФайла(ОписаниеОповещения, "C:1.xlsx", "D:1.xlsx"); КонецПроцедуры &НаКлиенте Процедура КопированиеФайлаЗавершение(СкопированныйФайл, ДополнительныеПараметры) Экспорт Сообщить(СкопированныйФайл); КонецПроцедуры
Здесь аналог приостановки – это завершение процедуры СкопироватьФайл после вызова метода НачатьКопированиеФайла. Аналог возобновления – это выполнение метода обратного вызова, указанного в описании оповещения, после завершения копирования файла. Отличие заключается в форме – вместо последовательного кода используется набор логически связанных процедур.
Поэтому ранее отмечалось, что глобально смысл асинхронности в платформе не изменился с появлением Обещаний. Изменился только способ написания кода.
Рассмотрим более сложный пример, демонстрирующий приостановку и возобновление программного кода. На форме есть реквизит с типом ТаблицаЗначений, у которой есть две колонки – ИмяФайла и Размер:
Необходимо найти в определенном каталоге все файлы с расширением xlsx и вывести в эту таблицу значений на форме имя и размер найденных файлов:
Программный код для решения поставленной задачи приведен ниже:
1 &НаКлиенте 2 Асинх Процедура ВывестиСведенияОФайлах(Команда) 3 ОбещаниеФайлы = ПолучитьСведенияОФайлах(); 4 МассивСведений = Ждать ОбещаниеФайлы; 5 ТаблицаФайлов.Очистить(); 6 Для каждого СведенияОФайле Из МассивСведений Цикл 7 НоваяСтрока = ТаблицаФайлов.Добавить(); 8 ЗаполнитьЗначенияСвойств(НоваяСтрока, СведенияОФайле); 9 КонецЦикла; 10 КонецПроцедуры 11 12 &НаКлиенте 13 Асинх Функция ПолучитьСведенияОФайлах() 14 Результат = Новый Массив; 15 ОбещаниеНайденныеФайлы = НайтиФайлыАсинх("C:UsersUser1Downloads", "*.xlsx", Ложь); 16 НайденныеФайлы = Ждать ОбещаниеНайденныеФайлы; 17 Для каждого НайденныйФайл Из НайденныеФайлы Цикл 18 ОбещаниеРазмерФайла = НайденныйФайл.РазмерАсинх(); 19 РазмерФайла = Ждать ОбещаниеРазмерФайла; 20 Результат.Добавить(Новый Структура("ИмяФайла, Размер", НайденныйФайл.Имя, РазмерФайла)); 21 КонецЦикла; 22 Возврат Результат; 23 КонецФункции
Разберем, в каком порядке будут выполняться строки этого асинхронного кода. Строки кода пронумерованы, чтобы удобнее было ссылаться на них.
- При нажатии на кнопку на форме срабатывает обработчик – процедура ВывестиСведенияОФайлах (строка 2). В строке 3 вызывается асинхронная функция ПолучитьСведенияОФайлах (строка 13).
- В строке 14 создается массив, в который будем помещать данные о найденных файлах. Функция ПолучитьСведенияОФайлах возвращает массив структур, каждая структура содержит имя и размер одного найденного файла.
- В строке 15 производится вызов асинхронной функции платформы НайтиФайлыАсинх. Эта функция возвращает Обещание, которое в строке 16 используется в качестве параметра оператора Ждать. Выполнение функции ПолучитьСведенияОФайлах приостанавливается, управление возвращается к вызвавшему эту функцию коду – в строку 3.
- Асинхронная функция ПолучитьСведенияОФайлах возвращает Обещание (строка 3). Это Обещание в строке 4 передается в качестве параметра оператора Ждать. Выполнение процедуры ВывестиСведенияОФайлах приостанавливается.
- Получается, что в данный момент существует 2 Обещания (ОбещаниеФайлы и ОбещаниеНайденныеФайлы), которые предназначены для хранения еще неизвестных результатов функций ПолучитьСведенияОФайлах и НайтиФайлыАсинх соответственно. Эти функции еще не завершили выполнение, поэтому невозможно получить их результат, нужно дождаться их выполнения. При этом важно, что система не может ждать выполнения обещаний нескольких асинхронных методов одновременно. Это может происходить только последовательно.
- После завершения работы функции НайтиФайлыАсинх происходит возобновление выполнения функции ПолучитьСведенияОФайлах в строке 16, восстанавливаются сохраненные на момент приостановки значения локальных переменных. В переменную НайденныеФайлы помещается массив объектов типа Файл. Остается только одно нерешенное Обещание – ОбещаниеФайлы.
- Выполнение кода перемещается на строку 17, в цикле перебираются элементы массива НайденныеФайлы.
- В строке 18 для каждого найденного файла вызывается асинхронная функция РазмерАсинх, которая возвращает еще одно Обещание – ОбещаниеРазмерФайла. В данный момент существует 2 Обещания (ОбещаниеФайлы и ОбещаниеРазмерФайла).
- В строке 19 используется оператор Ждать, поэтому еще раз происходит приостановка выполнения функции ПолучитьСведенияОФайлах. Получается, что никакой код в этот момент не выполняется, стек вызовов пустой, вернуть управление вызывающему коду нет возможности, поэтому управление возвращается платформе.
- После того, как размер файла определен, выполнение функции ПолучитьСведенияОФайлах возобновляется в строке 19. В переменной РазмерФайла содержится вычисленный размер файла, который был “спрятан” в ОбещаниеРазмерФайла.
- В строке 20 в массив Результат добавляется структура с именем и размером найденного файла. Строки 17-21 выполняются столько раз, сколько файлов было найдено, т.е. сколько элементов есть в массиве НайденныеФайлы.
- В строке 22 происходит возврат из функции ПолучитьСведенияОФайлах. Значит, ожидание в строке 4 завершается, в переменной МассивСведений содержится массив структур с информацией о найденных файлах.
- Остается только вывести полученные сведения о найденных файлах на экран, что происходит в строках 5-9.
- Выполнение процедуры ВывестиСведенияОФайлах завершается в строке 10.
Итак, вот в таком порядке выполняются строки кода, который выглядит последовательным, но фактически при его выполнении происходит приостановка и возобновление асинхронных методов.
Изобразим на схеме указанную последовательность шагов:
Особенности использования отладчика при работе с асинхронными функциями
Асинхронный код не выполняется строго линейно, в том порядке, как строки кода следуют друг за другом, поскольку происходят приостановки и возобновления выполнения, возврат управления вызывающему коду.
Для удобства разработчиков в отладчике была реализована “имитация” синхронного выполнения асинхронных функций. Это означает, что при выполнении команд Шагнуть через (F10) и Шагнуть в (F11) на строке, содержащей оператор Ждать, отладчик будет дожидаться завершения работы асинхронной функции, после чего перейдет к следующей строке кода. Хотя фактически при этом произойдет выход из текущего метода и передача управления вызвавшему эту функцию коду. За счет такого поведения “эмулируется” синхронная работа отладчика.
Рассмотрим пример. Есть следующий асинхронный код:
1 &НаКлиенте 2 Асинх Процедура ВывестиОтветНаВопрос(Команда) 3 Обещание = ОтветНаВопрос(); 4 Сообщить("Пользователь выбрал вариант"); 5 Сообщить(Ждать Обещание); 6 КонецПроцедуры 7 8 &НаКлиенте 9 Асинх Функция ОтветНаВопрос() 10 Возврат Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); 11 КонецФункции
Разработчик в отладчике остановился на строке 10, в которой используется оператор Ждать. При выполнении команды Шагнуть через (F10) в пользовательском режиме будет показан вопрос, а также выведено сообщение из строки 4. После ответа пользователя на вопрос указатель текущей строки кода перемещается на строку 11, хотя фактически строка 4 уже была выполнена.
Еще раз выполним команду Шагнуть через (F10). При этом указатель текущей строки окажется на строке 6, а не на строке 4, как это произошло бы при синхронных вызовах. Получается, что отладчик может оказаться не на той строке, на которой разработчик ожидает остановиться.
Такое поведение объясняется природой асинхронных вызовов, потому что при ожидании на строке 10 выполнение функции ОтветНаВопрос приостановливается, управление передается вызывающем коду в процедуру ВывестиОтветНаВопрос. Выводится сообщение в строке 4. В строке 5 используется оператор Ждать, поэтому происходит приостановка выполнения процедуры ВывестиОтветНаВопрос, управление возвращается платформе.
После того, как пользователь ответит на вопрос, выполнение функции ОтветНаВопрос возобновляется, происходит возврат из этой функции. Ожидание в строке 5 завершается, выводится сообщение с выбранным пользователем вариантом.
Поэтому отладчик показывает, что при выполнении шага со строки 11 указатель текущей строки оказывается на строке 6.
Чтобы разработчику было проще разобраться с порядком вызовов асинхронных функций, в инструменте Стек вызовов цветом выделяются строки. После возобновления асинхронной функции (текущая строка – 11) черным цветом будет выделен стек, выполняющийся в данный момент, а серым – стек, из которого была вызвана асинхронная функция:
Может сложиться ситуация, что исходная процедура, которая вызвала асинхронную функцию, к моменту возобновления работы функции уже завершила свое выполнение. Рассмотрим пример:
1 &НаКлиенте 2 Асинх Процедура ВывестиОтветНаВопрос(Команда) 3 ОтветНаВопрос(); 4 КонецПроцедуры 5 6 &НаКлиенте 7 Асинх Функция ОтветНаВопрос() 8 Ответ = Ждать ВопросАсинх("Выполнить загрузку?", РежимДиалогаВопрос.ДаНет); 9 Сообщить("Пользователь выбрал вариант"); 10 Сообщить(Ответ); 11 КонецФункции
Если в отладчике выполнить остановку на строке 11 и сделать шаг (нажатием F10 или F11), то произойдет выход из отладки, в строку 4 выполнение кода не попадет. Почему? Дело в том, что в строке 8 используется оператор Ждать, поэтому происходит приостановка выполнения функции ОтветНаВопрос, управление возвращается к вызывающему коду – процедуре ВывестиОтветНаВопрос. В строке 4 происходит завершение работы процедуры.
Когда пользователь ответит на вопрос, произойдет возобновление выполнения функции в строке 8, будут выведены сообщения из строк 9 и 10. При выходе из функции ОтветНаВопрос в строке 11 возвращаться уже некуда, поскольку вызвавший эту функцию код уже отработал. Но тем не менее в стеке вызовов этот код будет отображаться серым цветом:
Использование фоновых заданий для выполнения длительных операций
Ранее отмечалось, что асинхронность в платформе “1С:Предприятие” появилась из-за требований, предъявляемых браузерами. Например, существуют ограничения на время выполнения скриптов, чтобы предотвратить блокировку интерфейса браузера.
В типовых конфигурациях есть длительные процедуры, такие, как заполнение документов по данным информационной базы, при этом во время заполнения пользователь может работать с другими объектами – формировать отчеты, создавать документы. Рассмотрим, как организовано такое выполнение операций, не блокирующее работу пользователей. И самое главное – выясним, как оно связано с асинхронностью.
Для примера рассмотрим типовую конфигурацию “Бухгалтерия предприятия”. В документе СчетФактураВыданный есть форма ФормаДокументаКорректировочнаяСправка. В этой форме реализован обработчик команды Заполнить. Поскольку заполнение документа может занять длительное время, эта операция выполняется с помощью фонового задания.
Код, заполняющий документ, располагается в модуле менеджера документа, в процедуре ПодготовитьДанныеДляЗаполненияКорректировочнойСправки. В этой процедуре данные из базы, необходимые для заполнения документа, помещаются во временное хранилище.
Запускается фоновое задание, исполняющее этот код. Отображается общая форма с анимированной картинкой:
Если за определенное время фоновое задание не завершилось, в форме документа подключается обработчик ожидания, который периодически проверяет состояние фонового задания. Когда фоновое задание успешно завершено, из временного хранилища извлекаются данные, помещаются в табличную часть документа.
Для доступа из формы к результату заполнения документа, помещенному в фоновом задании во временное хранилище, используется реквизит формы АдресХранилища. Чтобы из клиентского приложения можно было проверить состояние запущенного фонового задания (завершено успешно, еще выполняется или завершено с ошибкой), его идентификатор также хранится в реквизите формы ИдентификаторЗадания:
Приведем фрагменты программного кода модуля формы, которые имеют отношение к фоновому заполнению документа. При помощи комментариев отметим назначение отдельных процедур или переменных.
//Клиентские переменные для управления формой длительной операции &НаКлиенте Перем ПараметрыОбработчикаОжидания; &НаКлиенте Перем ФормаДлительнойОперации; //Обработчик команды Заполнить &НаКлиенте Процедура Заполнить(Команда) Если Объект.ДокументыОснования.Количество() <> 0 Тогда Если Объект.Проведен Тогда ТекстВопроса = НСтр("ru = 'Перед заполнением проведение документа будет отменено, а список документов-основанией будет очищен. Заполнить?'"); Иначе ТекстВопроса = НСтр("ru = 'Список документов-основанией будет очищен. Заполнить?'"); КонецЕсли; Оповещение = Новый ОписаниеОповещения("ВопросЗаполнитьДокументЗавершение", ЭтотОбъект); ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет); Иначе ЗаполнитьДокумент(); КонецЕсли; КонецПроцедуры //Метод обратного вызова, выполняемый после того, как пользователь ответит на вопрос &НаКлиенте Процедура ВопросЗаполнитьДокументЗавершение(Результат, ДополнительныеПараметры) Экспорт Если Результат = КодВозвратаДиалога.Да Тогда ЗаполнитьДокумент(); КонецЕсли; КонецПроцедуры //Подключение обработчика ожидания для проверки выполнения фонового задания &НаКлиенте Процедура ЗаполнитьДокумент() Результат = ЗаполнитьДокументНаСервере(); Если Результат.ЗаданиеВыполнено Тогда ОповеститьОбИзменении(Объект.Ссылка); Иначе ИдентификаторЗадания = Результат.ИдентификаторЗадания; АдресХранилища = Результат.АдресХранилища; ДлительныеОперацииКлиент.ИнициализироватьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания); ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания", 1, Истина); ФормаДлительнойОперации = ДлительныеОперацииКлиент.ОткрытьФормуДлительнойОперации(ЭтаФорма, ИдентификаторЗадания); КонецЕсли; КонецПроцедуры //Серверный метод, запускающий фоновое задание &НаСервере Функция ЗаполнитьДокументНаСервере() Если Объект.Проведен Тогда Записать(Новый Структура("РежимЗаписи", РежимЗаписиДокумента.ОтменаПроведения)); КонецЕсли; Объект.ДокументыОснования.Очистить(); СтруктураПараметров = Новый Структура("Ссылка, Организация, Дата, ИсправляемыйСчетФактура", Объект.Ссылка, Объект.Организация, Объект.Дата, Объект.ИсправляемыйСчетФактура); Если ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор); Документы.СчетФактураВыданный.ПодготовитьДанныеДляЗаполненияКорректировочнойСправки(СтруктураПараметров, АдресХранилища); Результат = Новый Структура("ЗаданиеВыполнено", Истина); Иначе НаименованиеЗадания = НСтр("ru = 'Заполнение документа ""Корректировочная справка по розничным продажам""'"); Результат = ДлительныеОперации.ЗапуститьВыполнениеВФоне( УникальныйИдентификатор, "Документы.СчетФактураВыданный.ПодготовитьДанныеДляЗаполненияКорректировочнойСправки", СтруктураПараметров, НаименованиеЗадания); АдресХранилища = Результат.АдресХранилища; КонецЕсли; Если Результат.ЗаданиеВыполнено Тогда ЗагрузитьПодготовленныеДанные(); КонецЕсли; Возврат Результат; КонецФункции //Проверка выполнения задания по его идентификатору &НаСервереБезКонтекста Функция ЗаданиеВыполнено(ИдентификаторЗадания) Возврат ДлительныеОперации.ЗаданиеВыполнено(ИдентификаторЗадания); КонецФункции //Проверка, нужно ли закрыть форму длительной операции. Установка интервала ожидания &НаКлиенте Процедура Подключаемый_ПроверитьВыполнениеЗадания() Попытка Если ФормаДлительнойОперации.Открыта() И ФормаДлительнойОперации.ИдентификаторЗадания = ИдентификаторЗадания Тогда Если ЗаданиеВыполнено(ИдентификаторЗадания) Тогда ЗагрузитьПодготовленныеДанные(); ДлительныеОперацииКлиент.ЗакрытьФормуДлительнойОперации(ФормаДлительнойОперации); Иначе ДлительныеОперацииКлиент.ОбновитьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания); ПодключитьОбработчикОжидания( "Подключаемый_ПроверитьВыполнениеЗадания", ПараметрыОбработчикаОжидания.ТекущийИнтервал, Истина); КонецЕсли; КонецЕсли; Исключение ДлительныеОперацииКлиент.ЗакрытьФормуДлительнойОперации(ФормаДлительнойОперации); ВызватьИсключение; КонецПопытки; КонецПроцедуры //Получение данных из временного хранилища, загрузка в табличную часть документа &НаСервере Процедура ЗагрузитьПодготовленныеДанные() СтруктураДанных = ПолучитьИзВременногоХранилища(АдресХранилища); Если ТипЗнч(СтруктураДанных) <> Тип("Структура") Тогда Возврат; КонецЕсли; Если СтруктураДанных.Свойство("ДокументыОснования") Тогда Объект.ДокументыОснования.Загрузить(СтруктураДанных.ДокументыОснования); КонецЕсли; //работа с формой... Модифицированность = Истина; КонецПроцедуры
Подобный код, выполняющий длительные операции в фоновом задании, можно встретить во всех конфигурациях на базе БСП – Управление торговлей 11, Комплексная автоматизация 2, Зарплата и управление персоналом 3 и другие.
Также в демонстрационной базе БСП можно ознакомиться, как работает этот механизм. Для демонстрации возможностей подсистемы в демо-базе реализована обработка _ДемоДлительнаяОперация.
Обратите внимание, что данный программный код значительно отличается от рассмотренного ранее асинхронного кода.
В коде не используются асинхронные процедуры, имя которых начинается с Показать или Начать, также нет функций с модификатором Асинх.
Запуск фонового задания производится на сервере, в то время, как асинхронные методы, разбираемые в предыдущих главах, являются клиентскими. Вообще работа с фоновыми заданиями производится только на сервере. Например, проверка того, выполнено ли задание, выполняется в серверной функции.
Для работы фонового задания создается отдельный сеанс, в котором и выполняется длительная операция. При вызове асинхронных методов отдельный сеанс не создается, все действия выполняются в одном сеансе. В целом асинхронность в платформе не является реализацией многопоточности.
При вызове асинхронной процедуры в описании оповещения указывается, какую процедуру необходимо выполнить при завершении работы асинхронного метода. При использовании оператора Ждать происходит приостановка выполнения метода, после завершения работы асинхронной функции выполняется возобновление приостановленного метода. Таким образом, из программного кода не нужно проверять, отработал ли уже асинхронный метод. Платформа самостоятельно выполнит нужное действие – передаст управление методу обратного вызова или возобновит приостановленный метод.
При выполнении длительных действий в фоновом задании нет возможности получить “уведомление” от сервера, что фоновое задание завершено, чтобы получить подготовленные данные и загрузить их в табличную часть документа. Поэтому приходится подключать обработчик ожидания, который с заданной периодичностью проверяет состояние фонового задания с определенным идентификатором. Как только такая проверка определяет, что фоновое задание завершилось, можно приступать к обработке данных, помещенных во временное хранилище в фоновом задании.
Таким образом, длительные операции с использованием фоновых заданий и асинхронные методы – это принципиально разные механизмы. Правда на практике достаточно часто термин “асинхронное выполнение” применяется и для способа с фоновыми заданиями, поскольку при этом не блокируется интерфейс приложения. Поэтому обязательно нужно уточнять, какая именно асинхронность имеется в виду.
Заключение
Итак, в данной статье продемонстрировано, что современные браузеры диктуют требования, из-за которых фирме “1С” пришлось добавить асинхронные методы в платформу “1С:Предприятие”.
Отличие асинхронного метода от синхронного заключается в том, что асинхронный метод не блокирует основной поток выполнения кода. После вызова асинхронного метода управление вернется к коду, вызвавшему этот метод, до того, как сам асинхронный метод завершит свою работу.
Существует 2 варианта асинхронных методов – с использованием методов обратного вызова и с использованием нового типа данных Обещание и оператора Ждать, которые появились в платформе 8.3.18.
Использование асинхронных процедур с методами обратного вызова приводит к тому, что код становится фрагментированным. Это усложняет разработку кода.
Поэтому фирма “1С” упростила работу разработчикам, добавив в платформу 8.3.18 асинхронные функции, возвращающие Обещания. Использование таких методов делает код более понятным, простым для анализа и модификации – похожим на код с использованием аналогичных синхронных методов.
В феврале 2021 года использование платформы 8.3.18 для работы с типовыми конфигурациями не является обязательным. Поэтому новые асинхронные функции, возвращающие Обещания, еще нельзя встретить в коде. Ожидается, что в скором времени этот функционал будет использоваться повсеместно – начиная с БСП, откуда он попадет во все типовые конфигурации, базирующихся на БСП.
Сейчас как раз есть время подготовиться, изучить новый функционал, разобраться с асинхронностью в платформе “1С:Предприятие”. Когда в БСП и в типовых начнут применяться асинхронные функции – это не будет неожиданностью. К тому же с кодом станет работать удобнее, проще, разработчики смогут сконцентрироваться на реализации алгоритмов, а не на преодолении сложностей встроенного языка.
База с приведенными в статье фрагментами кода
Хотите еще?
Кроме этой статьи мы опубликовали несколько видео-уроков по использованию асинхронных методов «Как выводить сообщения пользователю без километров кода» от Сергея Калинкина (автор курса «Интерфейсы и формы»).
33 минуты, рекомендуем к просмотру
Не пропустите новый курс (по специальной цене для первого потока)!
Коллеги, запускаем новый курс по EDT и Git, первый курс в серии курсов по DevOps.
Если Вы тимлид / руководитель отдела разработки / работаете в команде из 5+ человек над одним проектом / планируете перейти в ведущие франчайзи не простым разработчиком – рекомендуем внимательно его посмотреть: