Что такое promise зачем нужен async await

Async/await: 6 причин забыть о промисах

Если вы не в курсе, в Node.js, начиная с версии 7.6, встроена поддержка механизма async/await. Говорят о нём, конечно, уже давно, но одно дело, когда для использования некоей функциональности нужны «костыли», и совсем другое, когда всё это идёт, что называется, «из коробки». Если вы ещё не пробовали async/await — обязательно попробуйте.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Основы async/await

Для тех, кто не знаком с async/await, вот основные вещи, которые полезно будет знать прежде чем двигаться дальше.

Синтаксис

С использованием промисов подобное можно реализовать так:

Вот как то же самое делается с использованием async/await:

Если сопоставить два вышеприведённых фрагмента кода, можно обнаружить следующее:

Почему async/await лучше промисов?

Рассмотрим обещанные шесть преимуществ async/await перед традиционными промисами.

▍1. Лаконичный и чистый код

▍2. Обработка ошибок

Вот то же самое, переписанное с использованием async/await. Блок catch теперь будет обрабатывать и ошибки, возникшие при парсинге JSON.

▍3. Проверка условий и выполнение асинхронных действий

Представьте, что надо написать кусок кода, который, загрузив некие данные, принимает решение о том, вернуть ли их в точку вызова, или, основываясь на том, что уже получено, запросить ещё что-нибудь. Решить подобную задачу можно так:

Только от взгляда на эту конструкцию может разболеться голова. Очень легко потеряться во вложенных конструкциях (тут их 6 уровней), скобках, командах возврата, которые нужны лишь для того, чтобы доставить итоговый результат главному промису.

Код будет гораздо легче читать, если решить задачу с использованием async/await.

▍4. Промежуточные значения

При таком подходе семантика приносится в жертву читабельности кода. Нет причин для того, чтобы помещать value1 и value2 в один и тот же массив за исключением того, чтобы избежать вложенности промисов.

То же самое можно написать с применением async/await, причём делается это удивительно просто, а то, что получается, оказывается интуитивно понятным. Тут поневоле задумаешься о том, сколько полезного можно сделать за то время, которое тратится на написание хоть сколько-нибудь приличного кода с использованием промисов.

▍5. Стеки ошибок

Представьте себе фрагмент кода, в котором имеется цепочка вызовов промисов, а где-то в этой цепочке выбрасывается ошибка.

Если же взглянуть на подобную ситуацию при использовании async/await, стек ошибки укажет на ту функцию, в которой возникла проблема.

▍6. Отладка

Этот пункт последний, но это не значит, что он не особо важен. Ценнейшая особенность использования async/await заключается в том, что код, в котором задействована эта конструкция, гораздо легче отлаживать. Отладка промисов всегда была кошмаром по двум причинам.

1. Нельзя установить точку останова в стрелочных функциях, которые возвращают результаты выполнения выражений (нет тела функции).

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Попробуйте поставить где-нибудь в этом коде точку останова

При использовании async/await особой нужды в стрелочных функциях нет, и можно «шагать» по вызовам, выполненным с ключевым словом await так же, как это делается при обычных синхронных вызовах.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Отладка при использовании async/await

Замечания

Вполне возможно, у вас возникнут некоторые соображения не в пользу применения async/await, продиктованные здоровым скептицизмом. Прокомментируем пару наиболее вероятных.

Выводы

Пожалуй, async/await — это одна из самых полезных революционных возможностей, добавленных в JavaScript в последние несколько лет. Она даёт простые и удобные способы написания и отладки асинхронного кода. Полагаем, async/await пригодится всем, кому приходится писать такой код.

Уважаемые читатели! Как вы относитесь к async/await? Пользуетесь ли вы этой возможностью в своих проектах?

Источник

Углубляемся в JavaScript: всё ли может async/await, или когда использовать Promise

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

руководитель AFFINAGE

Что такое async/await и promise?

Прежде чем ответить на поставленный вопрос, нам необходимо узнать немного теории.

Асинхронность меняет сложившуюся парадигму последовательного кода. Последовательность — когда только одна конкретная операция происходит в данный момент времени. Если функция зависит от результата выполнения другой функции, то она должна дождаться пока прошлая функция не завершит свою работу. Для пользователя это значит состояние вечного «ждуна».

Асинхронность нужна нам, чтобы делать несколько операций и функций параллельно. Асинхронное программирование — это инструмент для оптимизации высоконагруженных сайтов с долгими и частыми ожиданиями обратной связи. Например, когда одна функция создаёт canvas на странице, другая функция может подготовить данные необходимые для отрисовки внутри canvas. Ещё пример, когда пользователь кладет товар в корзину ему не обязательно ждать ответа сервера, мы заранее можем показать анимацию добавления товара в корзину, а всю остальную логику проверок сделать после ответа сервера, не блокируя интерфейс пользователю.

На самом деле с точки зрения машинного кода, async/await и промисы это абсолютно то же самое. Но мы то с вами люди, и нам важен синтаксис. И разница в синтаксисе настолько существенна, что разделила разработчиков на два лагеря. Любители колбэков выбрали Promise, а не любители цепочек выбрали async/await.

Async/await — синтаксис работающий с промисами, придуман как альтернатива синтаксису промисов. Используя async, можно полностью избежать использования цепочек промисов с помощью await. Async создает Promise. А await ждет выполнения промиса.

Давайте посмотрим практические маленькие примеры синтаксиса.

Так как async является надстройкой над промисами, то мы можем смешивать код, например так:

Плюсы и минусы в теории

Async/await
Плюсы

Promise
Плюсы

На примерах выше видно, что Promise субъективно является более чистым кодом. Более того я заранее заложил одну противную пакость в примерах, о которой расскажу позже. Эта особенность не позволяет выбранному нами синтаксису использовать асинхронность в полной мере. Кто её нашел сходу, может дальше не читать 🙂

Вера в обещание

Шло время, навыки оттачивались, и с тех пор я всегда пишу js-код на промисах.

А теперь о пакости.

Сложный кейс с промисами, и главное преимущество промисов — колбеки

Попалась мне интереснейшая задача «Платежная система отвечает об успешной оплате не сразу, поэтому придется слать несколько запросов в течение 30 секунд, при этом держать пользователя в режиме прелоадера, при этом если оплата пройдет раньше чем 30 секунд, то из цикла нужно выйти и отключить прелоадер, и если за 30 секунд ответа не получено, то показать ошибку».

Для удобства сопоставления алгоритма и архитектуры код совсем чуть-чуть упрощен, и совпадает с оригинальным на 90%.

На данном примере видно как используются колбэки — у нас есть полный простор в передаче ошибок в родительский промис, их множественный вызов в разных местах, когда нам необходимо. И также максимальный простор для выбора момента уведомления «родителя» об успешном окончании, тем самым мы решаем 5 пункт из запланированной архитектуры.

Требование заказчика

История закончилась бы замечательно, если бы не одно «но». ТЗ требовало, чтобы весь код был написан на async/await. Глядя на код выше можно сказать, что это достаточно сложный кейс. Первое, что можно подумать: «Это невозможно! Ведь async/await не могут ждать колбека, они только выполняют код и ничего не ждут.»

Ну хорошо… требование заказчика — закон… переписываем.

Вывод

Нет ничего хуже, чем смешение разных стилей написания кода на одном проекте. Поэтому выбирайте стайлгайд по асинхронному коду заранее. Описанный выше кейс — это редкость. И зачастую async/await будет достаточно. Но если вы чувствуете, что на проекте будут сложные кейсы и есть вероятность использования колбэков, то используйте изначально промисы, применение конструкторов Promise тоже редкость. Остальное дело вкуса.

Источник

Async/await

Существует специальный синтаксис для работы с промисами, который называется «async/await». Он удивительно прост для понимания и использования.

Асинхронные функции

У слова async один простой смысл: эта функция всегда возвращает промис. Значения других типов оборачиваются в завершившийся успешно промис автоматически.

Например, эта функция возвратит выполненный промис с результатом 1 :

Можно и явно вернуть промис, результат будет одинаковым:

Await

Ключевое слово await заставит интерпретатор JavaScript ждать до тех пор, пока промис справа от await не выполнится. После чего оно вернёт его результат, и выполнение кода продолжится.

В этом примере промис успешно выполнится через 1 секунду:

В данном примере выполнение функции остановится на строке (*) до тех пор, пока промис не выполнится. Это произойдёт через секунду после запуска функции. После чего в переменную result будет записан результат выполнения промиса, и браузер отобразит alert-окно «готово!».

Обратите внимание, хотя await и заставляет JavaScript дожидаться выполнения промиса, это не отнимает ресурсов процессора. Пока промис не выполнится, JS-движок может заниматься другими задачами: выполнять прочие скрипты, обрабатывать события и т.п.

Ошибки не будет, если мы укажем ключевое слово async перед объявлением функции. Как было сказано раньше, await можно использовать только внутри async –функций.

Давайте перепишем пример showAvatar() из раздела Цепочка промисов с помощью async/await :

Получилось очень просто и читаемо, правда? Гораздо лучше, чем раньше.

Можно обернуть этот код в анонимную async –функцию, тогда всё заработает:

В примере ниже, экземпляры класса Thenable будут работать вместе с await :

Для объявления асинхронного метода достаточно написать async перед именем:

Обработка ошибок

Делает то же самое, что и такой:

Но есть отличие: на практике промис может завершиться с ошибкой не сразу, а через некоторое время. В этом случае будет задержка, а затем await выбросит исключение.

Так сделано в строке (*) в примере выше.

Итого

Ключевое слово async перед объявлением функции:

Ключевое слово await перед промисом заставит JavaScript дождаться его выполнения, после чего:

Вместе они предоставляют отличный каркас для написания асинхронного кода. Такой код легко и писать, и читать.

Источник

Визуализация промисов и Async/Await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Доброго времени суток, друзья!

Представляю вашему вниманию перевод статьи «JavaScript Visualized: Promises & Async/Await» автора Lydia Hallie.

Приходилось ли вам сталкиваться с JavaScript кодом, который… работает не так, как ожидается? Когда функции выполняются в произвольном, непредсказуемом порядке, или выполняются с задержкой. Одна из главных задач промисов — упорядочение выполнения функций.

Мое ненасытное любопытство и бессонные ночи окупились сполна — благодаря им я создала несколько анимаций. Пришло время поговорить о промисах: как они работают, почему их следует использовать и как это делается.

Введение

При написании JS кода нам часто приходится иметь дело с задачами, которые зависят от других задач. Допустим, мы хотим получить изображение, сжать его, применить к нему фильтр и сохранить его.

В результате получаем следующее:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Хм… Что-нибудь заметили? Несмотря на то, что все работает, выглядит это не лучшим образом. Мы получаем множество вложенных функций обратного вызова, зависящих от предыдущих коллбэков. Это называется адом коллбэков и это существенно усложняет чтение и поддержку кода.

К счастью, сегодня у нас есть промисы.

Синтаксис промисов

Промисы были представлены в ES6. Во многих руководствах вы можете прочитать следующее:

Промис (обещание) — это значение, которое выполняется или отклоняется в будущем.

Да уж… Так себе объяснение. В свое время оно заставило меня считать промисы чем-то странным, неопределенным, какой-то магией. Чем же они являются на самом деле?

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Погодите, что здесь возвращается?

PromiseStatus или статус промиса может принимать одно из трех значений:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Посмотрим, что выводится в консоль при вызове методов resolve и reject :

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

[[PromiseValue]] или значением промиса является значение, которое мы передаем методам resolve или reject в качестве аргумента.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Во введении я привела пример, в котором мы получаем изображение, сжимаем его, применяем к нему фильтр и сохраняем его. Тогда все закончилось адом коллбэков.

К счастью, промисы помогают с этим справиться. Перепишем код так, чтобы каждая функция возвращала промис.

Если изображение загрузилось, выполняем промис. В противном случае, если произошла ошибка, отклоняем промис:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Посмотрим, что происходит при запуске этого кода в терминале:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Клево! Промис возвращается с разобранными («распарсенными») данными, как мы и ожидали.

Но… что дальше? Нас не интересует объект промиса, нас интересуют его данные. Для получения значения промиса существует 3 встроенных метода:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Наконец, мы получили искомое значение. Мы можем делать с этим значением все что угодно.

Когда мы уверены в выполнении или отклонении промиса, можно писать Promise.resolve или Promise.reject с соответствующим значением.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Именно такой синтаксис будет использоваться в следующих примерах.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Такой синтаксис выглядит гораздо лучше лестницы вложенных функций обратного вызова.

Микрозадачи и (макро)задачи

Хорошо, теперь мы знаем, как создавать промисы и как извлекать из них значения. Добавим немного кода в наш скрипт и запустим его снова:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Точно. В цикле событий (Event Loop) существует два типа очередей: очередь (макро)задач или просто задач ((macro)task queue, task queue) и очередь микрозадач или просто микрозадачи (microtask queue, microtasks).

Что относится к каждой из них? Если вкратце, то:

Сначала Task1 возвращает значение и удаляется из стека. Затем движок проверяет наличие микрозадач в соответствующей очереди. После добавления и последующего удаления из стека микрозадач, движок проверяет наличие макрозадач, которые также добавляются в стек и удаляются из него после возврата значений.

Довольно слов. Давайте писать код.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Движок видит, что стек пуст. Он «заглядывает» в очередь микрозадач. Она тоже пуста.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Готово. Теперь все встало на свои места, не правда ли?

Async/Await

В ES7 был представлен новый способ работы с асинхронным кодом в JS. С помощью ключевых слов async и await мы можем создать асинхронную функцию, неявно возвращающую промис. Но… как нам это сделать?

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Получается, что мы можем отложить выполнение асинхронной функции? Отлично, но… что это значит?

Посмотрим, что происходит при запуске следующего кода:

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

После этого выполнение асинхронной функции откладывается. Выполнение тела функции приостанавливается, оставшийся код выполняется как микрозадача.

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

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

Что такое promise зачем нужен async await. Смотреть фото Что такое promise зачем нужен async await. Смотреть картинку Что такое promise зачем нужен async await. Картинка про Что такое promise зачем нужен async await. Фото Что такое promise зачем нужен async await

Получилось довольно многословно. Не переживайте, если чувствуете себя неуверенно при работе с промисами. Для того, чтобы к ним привыкнуть требуется какое-то время. Это характерно для всех приемов работы с асинхронным кодом в JS.

Спасибо за потраченное время. Надеюсь оно было потрачено не зря.

Источник

Асинхронное программирование с async/await

Доброго времени суток, друзья!

Сравнительно новыми дополнениями JavaScript являются асинхронные функции и ключевое слово await. Эти возможности в основном являются синтаксическим сахаром над обещаниями (промисами), облегчая написание и чтение асинхронного кода. Они делают асинхронный код похожим на синхронный. Данная статья поможет вам разобраться, что к чему.

Условия: базовая компьютерная грамотность, знание основ JS, понимание азов асинхронного кода и обещаний.
Цель: понять, как устроены обещания, и как они используются.

Основы async/await

Использование async/await состоит из двух частей.

Ключевое слово async

Прежде всего, у нас есть ключевое слово async, которое мы помещаем перед объявлением функции, чтобы сделать ее асинхронной. Асинхронная функция — это функция, которая предвосхищает возможность использования ключевого слова await для запуска асинхронного кода.

Попробуйте набрать в консоли браузера следующее:

Функция вернет ‘Hello’. Ничего необычно, верно?

Но что если мы превратим ее в асинхронную функцию? Попробуйте сделать следующее:

Теперь вызов функции возвращает обещание. Это одна из особенностей асинхронных функций — они возвращают значения, которые гарантировано преобразуются в обещания.

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

Также можно использовать стрелочные функции:

Все эти функции делают одно и тоже.

Таким образом, добавление ключевого слова async заставляет функцию возвращать обещание вместо значения. Кроме того, это позволяет синхронным функциям избегать любых накладных расходов, связанных с запуском и поддержкой использования await. Простое добавление async перед функцией обеспечивает автоматическую оптимизацию кода движком JS. Круто!

Ключевое слово await

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

Вы можете использовать await при вызове любой функции, возвращающей обещание, включая функции Web API.

Вот тривиальный пример:

Разумеется, приведенный код бесполезен, он лишь служит демонстрацией синтаксиса. Давайте двигаться дальше и посмотрим на реальный пример.

Переписываем код на обещаниях с использованием async/await

Возьмем пример с fetch из предыдущей статьи:

У вас уже должны быть понимание того, что такое обещания и как они работают, но давайте перепишем этот код с использованием async/await, чтобы увидеть насколько все стало проще:

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

Вы можете переписать пример или запустить наше живое демо (см. также исходный код).

Но как это работает?

Мы обернули код внутри функции и добавили ключевое слово async перед ключевым словом function. Вам нужно создать асинхронную функцию, чтобы определить блок кода, в котором будет запускаться асинхронный код; await работает только внутри асинхронных функций.

Еще раз: await работает только в асинхронных функциях.

Значение, возвращаемое обещанием fetch(), присваивается переменной response, когда данное значение становится доступным, и «парсер» останавливается на этой линии до завершения обещания. Как только значение становится доступным, парсер переходит к следующей строчке кода, которая создает Blob. Эта строчка также вызывает основанный на обещаниях асинхронный метод, поэтому здесь мы также используем await. Когда результат операции возвращается, мы возвращаем его из функции myFetch().

Добавляем обработку ошибок

Если вы хотите добавить обработку ошибок, у вас есть несколько вариантов.

Вы можете использовать синхронную структуру try. catch вместе с async/await. Этот пример является расширенной версией приведенного выше кода:

Блок catch()<> принимает объект ошибки, который мы назвали «e»; теперь мы можем вывести его в консоль, это позволит нам получить сообщение о том, в каком месте кода произошла ошибка.

Ожидание Promise.all()

Async/await основан на обещаниях, так что вы можете использовать все возможности последних. К ним, в частности, относится Promise.all() — вы легко можете добавить await к Promise.all(), чтобы записать все возвращаемые значения способом, похожим на синхронный код. Снова возьмем пример из предыдущей статьи. Держите вкладку с ним открытой, чтобы сравнить с показанным ниже кодом.

С async/await (см. живое демо и исходный код) он выглядит так:

Мы легко превратили функцию fetchAndDecode() в асинхронную с помощью парочки изменений. Обратите внимания на строчку:

Недостатки async/await

Async/await имеет парочку недостатков.

Async/await делает код похожим на синхронный и в некотором смысле заставляет его вести себя более синхронно. Ключевое слово await блокирует выполнение следующего за ним кода до завершения обещания, как это происходит в синхронной операции. Это позволяет выполняться другим задачам, но ваш собственный код является заблокированным.

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

Существует шаблон проектирования, позволяющий смягчить эту проблему — отключение всех процессов обещаний путем сохранения объектов Promise в переменных и последующего их ожидания. Давайте посмотрим на то, как это реализуется.

В нашем распоряжении имеется два примера — slow-async-await.html (см. исходный код) и fast-async-await.html (см. исходный код). Оба примера начинаются с функции-обещания, которая имитирует асинхронную операцию с помощью setTimeout():

Затем следует асинхронная функция timeTest(), которая ожидает трех вызовов timeoutPromise():

Каждый из трех вызовов timeTest() завершается записью времени выполнения обещания, затем записывается время выполнения всей операции:

В каждом случае функция timeTest() отличается.

В slow-async-await.html timeTest() выглядит так:

Здесь мы просто ожидаем три вызова timeoutPromise, каждый раз устанавливая задержку в 3 секунды. Каждый вызов ждет завершения предыдущего — если вы запустите первый пример, то увидите модальное окно примерно через 9 секунд.

В fast-async-await.html timeTest() выглядит так:

Здесь мы сохраняем три объекта Promise в переменных, что заставляет связанные с ним процессы выполняться одновременно.

Далее мы ожидаем их результаты — поскольку обещания начинают выполняться одновременно, обещания завершатся также в одно время; когда вы запустите второй пример, то увидите модальное окно примерно через 3 секунды!

Вам следует осторожно тестировать код и помнить об этом при снижении производительности.

Еще одним незначительным неудобством является необходимость оборачивания ожидаемых обещаний в асинхронную функцию.

Использование async/await совместно с классами

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

Метод класса может быть использован следующим образом:

Поддержка браузеров

Одним из препятствий использования async/await является отсутствие поддержки старых браузеров. Эта возможность доступна почти во всех современных браузерах, также как обещания; некоторые проблемы существуют в Internet Explorer и Opera Mini.

Если вы хотите использовать async/await, но нуждаетесь в поддержке старых браузеров, можете использовать библиотеку BabelJS — она позволяет использовать новейший JS, преобразуя его в подходящий для конкретного браузера.

Заключение

Async/await позволяет писать асинхронный код, который легко читать и поддерживать. Несмотря на то, что async/await поддерживается хуже других способов написания асинхронного кода, его определенно стоит изучить.

Источник

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

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