Практическое введение в асинхронные функции JavaScript: ES2017 Async-Await

Практическое введение в асинхронные функции JavaScript: ES2017 Async-Await

От автора: возможность писать на JavaScript асинхронные функции является важным обновлением в ES2017.

Что такое асинхронные функции?

Асинхронные функции — это функции, которые возвращают promise. Мы обозначаем их, используя ключевое слово async.

Когда loadData возвращает объект, возвращаемое значение оборачивается в promise. По мере того, как это promise обрабатывается, выполняется обратный вызов then и консоль регистрирует ответ.

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

Когда loadData вызывается с аргументом 0, возникает ошибка. Эта ошибка оборачивается в отклоненный promise, который обрабатывается обратным вызовом catch.

В общем случае возвращаемые значения функции async оборачиваются в обработанный вызов promise, за исключением тех случаев, когда возвращаемое значение является promise. Тогда возвращается promise.

Ошибки, введенные в асинхронную функцию, вырезаются и оборачиваются в отклоненный promise.

Оператор await

Await — это префиксный оператор, который указывается перед promise. Пока promise после оператора await находится в состоянии ожидания, promise блокирует выполнение.

После того, как promise будет обработан, await возвращает значение исполнения promise. Если promise будет отклонен, await сбрасывает отклоненное значение. Давайте рассмотрим пример:

Оператор await может использоваться только в асинхронных функциях. Если из предыдущего примера удалить ключевое слово async, возникает ошибка:

Сочетание async и await

Мы уже знаем, что асинхронные функции возвращают promise. Мы также знаем, что ключевое слово await:

выполняет promise в качестве своего операнда,

должно использоваться в асинхронных функциях.

Как следствие, мы можем ожидать ответа асинхронных функций внутри асинхронных функций.

Эта гипотетическая функция loadData загружает две таблицы, обращаясь к серверу через API. Выполняется первый запрос 1. Выполнение loadData блокируется до тех пор, пока не будет обработан promise, возвращаемый asyncQuery1. После того, как станет доступен resultSet1, выполняется функция displayResultSet1.

После этого выполняется asyncQuery2. Обратите внимание, что эта функция вызывается только после обработки возвращаемого значения asyncQuery1. Другими словами, asyncQuery1 и asyncQuery2 выполняются синхронно. После того, как resultSet2 становится доступным, отображаются результаты.

В этом примере есть только одна проблема. Представьте, что веб-приложение имеет доступ к десяти конечным точкам API. Предположим, что каждый вызов сервера занимает в среднем одну секунду. Если наша страница может быть отображена только после того, как будут выполнены все десять асинхронных вызовов, нам придется ждать десять секунд, пока пользователь сможет просмотреть страницу. Это неприемлемо.

Вот почему имеет смысл выполнять асинхронные запросы параллельно. Мы можем использовать Promise.all для создания promise, который объединяет и выполняет свои аргументы параллельно.

В этом примере все запросы выполняются асинхронно. Если массив внутри Promise.all содержал десять запросов, и выполнение каждого запроса занимает одну секунду, время выполнения всего выражения Promise.all все равно составит одну секунду.

Однако эти два решения не эквивалентны. Предположим, что среднее время, затраченное на извлечение resultSet1, составляет 0,1 секунды, а на извлечение resultSet2 требуется одна секунда. В этом случае:

асинхронная версия экономит 0,1 секунды по сравнению с синхронной,

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

однако displayResultSet1 выполняется только после того, как все запросы будут получены в асинхронной версии. Это означает, что мы можем ожидать на 0,9 секунды больше по сравнению с синхронной версией.

Мы можем объединить преимущества двух версий, используя цепочку последовательных обратных вызовов then promise.

В этой версии кода запросы выполняются асинхронно, и соответствующая функция обработчика displayResultSet выполняется, как только соответствующий promise будет обработан. Это означает, что первый запрос отображается за 0,1 секунды, а второй — за одну секунду.

Параллельное выполнение без await

Удалим функции disableSave и enableSave из предыдущего примера:

Функция по-прежнему работает, как ожидалось, однако реализация становится сложной без каких-либо причин.

Мы могли бы просто выполнить два асинхронных запроса и их соответствующие обработчики один за другим, не оборачивая их в Promise.all:

Не используя await, мы не блокируем выполнение asyncQuery2 до того, как будет обработан promise asyncQuery1. Поэтому два запроса все равно выполняются параллельно. Обратите внимание, что эта реализация loadData даже не объявлена как async, так как нам не нужно возвращать обещание promise, и мы больше не используем ключевое слово await в функции.

Ожидание отклоненного promise

Бывают случаи, когда операнд await становится отклоненным promise. Например:

при чтении файла, который не существует,

при ошибке ввода-вывода,

при таймауте сеанса в случае вызова API,

наш promise будет отклонен.

Когда promise p отклоняется, await p, выдает ошибку. Как следствие, мы должны обрабатывать все источники ошибок путем размещения выражений, ожидающих появления ошибок, в блоках try-catch.

Позиция ключевого слова async

Во-первых, мы можем создавать именованные выражения асинхронных регулярных функций или функций стрелок.

При создании выражений функций async указывает перед ключевым словом function.

Заключение

Асинхронные функции — это функции, которые возвращают promise. Эти функции могут обрабатывать операции ввода-вывода, вызовы API и другие формы отложенного выполнения. Ожидание обработки promise возвращает обработанное значение promise или выдает ошибку при отклонении. Оператор await позволяет выполнять асинхронные функции последовательно или параллельно. Async-await дает вам элегантный способ обработки асинхронных функций, и, следовательно, это одно из самых полезных обновлений ES2017.

Источник: http://www.zsoltnagy.eu/a>

Редакция: Команда webformyself.

Курс по ES 6 (EcmaScript 6.0)

Прямо сейчас посмотрите курс по EcmaScript 6.0

Смотреть курс

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Я не робот.

Spam Protection by WP-SpamFree