JavaScript – это однопоточный язык программирования. Все задачи выполняются в очереди и последовательности, а задачи обычно выполняются синхронно одна за другой. Это побуждает нас, как разработчиков, изучать асинхронный способ программирования нашей сети, чтобы мы могли выполнять «неблокирующий» код при выполнении некоторых других задач. К счастью, в JavaScript у нас есть async/await, часть головоломки, о которой не так часто говорят, чтобы улучшить наш веб-сайт для выполнения неблокирующего кода при обработке других задач.
Прежде чем мы обсудим async/await, нам нужно понять циклы обработки событий, обратные вызовы и промисы.
Я хотел бы указать вам на эту документацию для четкого объяснения того, что такое циклы событий, обратные вызовы и обещания в JavaScript.
После того, как вы прочитали объяснение, позвольте мне спросить вас об этом фрагменте console.log
. Можете ли вы сказать мне, какова выходная последовательность этих 4 console.log
(s)?
Потратьте некоторое время, чтобы подумать об этом, прежде чем прокрутить вниз в поисках ответа.
Вы поняли это правильно? Последовательность событий следующая. Сначала будет запущена синхронная функция console.log
, функция setTimeout, хотя с тайм-аутом 0 мс, ей будет поручено запуститься в следующем/будущем цикле событий. . Блок Promise ставится в очередь в очереди микрозадач и будет выполняться непосредственно перед началом следующего цикла событий, следовательно, до setTimeout код.
Теперь, когда у вас есть более четкое представление о том, что такое циклы обработки событий, обратные вызовы и промисы, мы можем подробнее рассмотреть вызовы HTTP на основе промисов.
Если мы запустим этот HTTP-вызов на основе обещаний, console.log
сначала отобразит вывод кода синхронизации, а затем отобразит вывод «API вызван успешно». Как мы упоминали ранее, вызовы на основе промисов помещаются в очередь микрозадач. Прелесть HTTP-вызова на основе обещаний заключается в том, что он обрабатывает поиск данных и обработку ошибок при выполнении вызовов API. Если возникает ошибка, она пропускает все обратные вызовы then и переходит прямо к блоку catch.
Вот классический пример блокирующего кода в JavaScript.
Вывод второго кода синхронизации возможен только после завершения выполнения кода блокировки через 540 мс.
Таким образом, вы можете подумать, что можете просто обернуть цикл while внутри обещания, чтобы он выполнялся после синхронного кода.
Это отчасти верно, но второй синхронный код все еще блокируется до завершения цикла while. Однако вы можете поместить блокирующий код в Promise.resolve(), чтобы быть уверенным, что блокирующий код будет выполнен только после выполнения всего синхронного кода.
Теперь, когда вы понимаете, как асинхронный код может работать в вызове на основе обещаний, мы можем перейти к Async/Await и посмотреть, как это помогает нам, разработчикам, писать более чистый и читаемый код.
Когда вы пишете обычную функцию, которая ничего не возвращает, она просто возвращает void.
Но когда вы добавляете ключевое слово async перед скобками аргументов функции, возвращается promise‹void›.
Помимо использования ключевого слова async, технически вы можете просто вернуть Promise, который превратит вызов функции в возвращаемый тип того же типа.
Обе функции возвращают результаты на основе Promise. Однако сила появляется, когда вы используете ключевое слово async в сочетании с await.
Давайте поймем, что и makeDinner(), и makeLunch() получат желаемый результат: «курица», «лосось». Но разница в том, что makeDinner() использует ключевое слово await, что делает код более читабельным.
Если вызов 2-й функции независим от результата вызова 1-й функции, технически нам не нужно писать await таким образом. Так как это приведет к тому, что цикл событий будет ждать завершения 1-й функции перед выполнением 2-й функции.
Если мы напишем задержку 1000 мс в функции getIngredient(). Мы видим, что общее время выполнения getDinner() составляет 2002 мс, при этом каждая функция занимает около 1000 мс задержки.
Если результаты независимы друг от друга, мы можем написать неблокирующий код для выполнения обеих функций параллельно с помощью Promise. all и await для комбинации всех обещаний.
Затраченное время будет просто задержкой, которая происходит в функции getIngredients() once.
Обработка ошибок с помощью Async/Await
Обработка ошибок для async/await упрощается благодаря использованию в функции блочного кода try/catch.
Вы получаете полный контроль над тем, как вы хотите вернуть данные. Если в блоке try вы обнаружите ошибку, она будет перехвачена в блоке catch. Если вы обработаете его и вернете ошибку, вы увидите сообщение об ошибке в блоке then вашего makeDinner(). Если вы решите выдать ошибку, вы сможете увидеть сообщение об ошибке в блоке catch вашего makeDinner().
Последний, но тем не менее важный
Остерегайтесь использования async/await в цикле [].map или [].forEach.
Вы можете подумать, что они будут выполняться один за другим, но на самом деле они выполняются после разрешения promise.all. Если вы по-прежнему хотите, чтобы ваш цикл выполнялся синхронно, вы можете вместо этого использовать традиционный цикл for.
Но поскольку вы используете async/await, я предполагаю, что вы хотите запускать все одновременно без какого-либо блокирующего кода, поэтому в этом случае вы можете использовать этот синтаксис в цикле for, чтобы разрешить все одновременно. время.
Бонус
Вы также можете использовать async/awaitусловно в случаях if/else.
Краткое содержание
Надеюсь, эта статья поможет вам лучше понять, как работает async/await и как их обрабатывает JavaScript. Оставьте свой комментарий ниже, если у вас есть другие приемы async/await, которыми вы хотите поделиться с другими. Хорошего дня.
Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Получите эксклюзивный доступ к возможностям написания и советам в нашем сообществе Discord.