Как улучшить асинхронный код JavaScript с помощью async и await

Как улучшить асинхронный код JavaScript с помощью async и await

От автора: если вы имели возможность просматривать современный код Javascript — высока вероятность того, что вы где-нибудь видели синтаксис async и await. Async await JavaScript — это, пожалуй, одно из самых популярных нововведений в языке. Async / await заставляет асинхронный код отображаться и вести себя как синхронный. Async / await основаны на promise.

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

В любом случае, зачем нам асинхронный код?

Javascript — это однопоточный язык, это означает, что Javascript может делать только одну вещь одновременно. Представьте, что вы вызываете API синхронно и блокируете весь поток на время вызова API — нашим пользователям придется ждать 30 секунд или столько времени, сколько потребуется для разрешения сетевого запроса — о, нет!

Если вам интересно узнать больше — вот более подробное пояснение по асинхронному программированию с использованием Javascript.

Способ, который мы использовали для обработки асинхронного кода Javascript, был связан с обратными вызовами. Скорее всего, вы сталкивались с ними.

Что такое обратные вызовы?

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

Возможно, вы видели специфичный для jQuery код, подобный этому. Следующий код добавляет прослушиватель событий к кнопке и вызывает alert, когда он срабатывает. Где же здесь обратный вызов? — можете спросить вы. Это анонимная function в скобках функции click.

Обратные вызовы в двух словах: мы запускаем функцию, делаем что-то, а затем вызываем другую функцию.

Обратные вызовы — это не всегда плохо, они работали — и все еще работают. Но что произойдет, если у нас будет обратный вызов внутри обратного вызова внутри обратного вызова — вы поняли мою мысль. Это становится действительно грязным и медленным.

Эта проблема была названа «адом обратных вызовов».

Еще один пример.

Мы проверяем, есть ли у нас дыня внутри массива — если да, мы ее жуем, после этого мы выбрасываем дыню. Мы также обрабатываем исключения с помощью обратного вызова err.

Примечание: обратный вызов err в первом аргументе — это всегда в мире Node  лучшая практика!

Просто чтобы немного пояснить ситуацию — я сделал предыдущий код как можно более читабельным, вот как он мог выглядеть:

Мини-ад обратных вызовов; технически, можно было бы исправить это с помощью анонимных функций стрелок, но все же это не идеальное решение.

Вы можете себе представить, пара дополнительных обратных вызовов, и мы на пути в ад обратных вызовов!

Promises приходят на помощь!

Promises — это чистый способ написания асинхронного кода. Promises имеют единственный аргумент, который является обратным вызовом. Обратный вызов имеет два аргумента: условия reject и resolve.

И если мы используем функцию стрелки, чтобы сократить код:

Внутри блока promise мы можем решить, когда разрешить и когда отклонить promise.

Внутри promise мы проверяем, есть ли у нас дыня. Если это так, давайте resolve функцию со значением, которое мы передаем внутрь resolve - мы можем передать в resolve буквально любое значение. Promises немедленно вызываются / разрешаются, поэтому мы видим console.log без вызова promise.

Promises вызываются и задаются в последовательности с помощью методов then и catch. Представьте это так: promise был разрешен со значением — что мы будем с ним делать?

Вот где в дело вступает синтаксис then и catch. Они оба являются обратными вызовами, принимающими один аргумент, который является возвращаемым значением, передаваемым внутри обещания. Вот как мы можем обработать отклонение promise:

Хорошо, теперь наш promise не очень динамичен — почему? Ну, потому что у нас есть выражение if, которое не является динамическим. Promises чрезвычайно мощны, когда заключены в функцию. Мы называем их функциями высшего порядка.

Вы заметили небольшие изменения? Мы обернули promise в функцию, которая в этом случае принимает один аргумент. Это дает promise большую гибкость. Мы можем передать promise любое условие, и на основании этого условия он будет отклонен или разрешен.

Вот полностью рабочий promise, которые разрешается.

И отклоненный promise.

Начинает выглядеть знакомо? Возможно, вы видели вызовы Axios API, как показано ниже. Пример вызова Axios + React API (на основе promise):

Или вызов API Fetch. Пример вызова Fetch + react API (на основе promise):

Что у них общего? Ну, для начала promise. Они в основном используют promise «под капотом». Так же, как мы обернули наш promise внутри функции. Во-вторых, они оба — это асинхронный код. Promises естественно асинхронны. Вот как выглядит асинхронный вызов API:

Можно с уверенностью сказать, что promise намного лучше, чем обратные вызовы. Хотя у promise есть свои недостатки — они могут выйти из-под контроля довольно быстро. Что, если есть лучший способ, еще более чистый. Async/await!

//codesandbox.io/s/p9mr3jzwp0?autoresize=1&expanddevtools=1&hidenavigation=1

Мы помечаем функцию, как async - внутри функции мы помечаем асинхронный код, как await - Javascript разрешает promise и затем переходит к следующей строке. Короче говоря, мы изменяем асинхронный код, чтобы он читался как синхронный, в то же время работая асинхронно.

Обратите внимание, что мы больше не вызываем конструктор promise и что у нас намного меньше методов then() и catch().

Как насчет обработки ошибок?

Наши текущие async / await не обрабатывает исключения. Это может привести к катастрофическим ошибкам, которые могут привести к сбою приложения. Try…catch приходит на помощь!

Блок try catch пытается выполнить код, и если он сталкивается с какими-либо исключениями / проблемами, то передает объект ошибки в блок catch и выполняет код внутри блока catch. Вот как будет выглядеть наша async/await с обработкой ошибок.

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

Автор: Indrek Lasn

Источник: //medium.freecodecamp.org/

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

Метки:

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

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