Как работает Async/Await?
Несмотря на все причудливые функции, встроенные в современные языки программирования, внутри они все еще довольно примитивны. Без асинхронного программирования длительные вызовы внешних служб прерывали бы выполнение программы. Async/await решает эту проблему.
Зачем использовать Async/Await?
Большинство программ используют один основной поток и выполняют инструкции ЦП последовательно, но, что более важно, синхронно. Если вам нужно извлечь значение из памяти, вы на некоторое время застряли в IOWait, ожидая, пока ваша оперативная память освободится. вернуть ответ. Если вам нужно получить значение с диска, вы можете застрять на некоторое время (поэтому ОЗУ так полезно).
Но если вы получаете что-то с удаленного сервера, у вас большие проблемы. Серверу может потребоваться 5 секунд или более, чтобы вернуть ответ, а в однопоточной программе это заблокирует основное выполнение, в результате чего ваша страница перестанет отвечать на запросы, а ваши пользователи уйдут.
Асинхронное программирование здесь, чтобы спасти пользователей. В JavaScript наиболее простой формой асинхронного кода является передача обратного вызова, обычно анонимной функции, которая запускается после завершения веб-запроса. Это можно сделать с помощью Ajax и других библиотек запросов.
ajax('https://example.com/api', (response) => { console.log(response); });
Это может стать очень запутанным при работе с несколькими одновременными запросами и множеством функций, поэтому JavaScript создал промисы. Это объекты-оболочки, представляющие асинхронные переменные, которые все еще получают свои значения. Промисы могут быть возвращены при использовании таких функций, как встроенная в JavaScript функция fetch
. Вы можете зарегистрировать функцию обратного вызова, используя .then()
, что позволит вам объединить несколько запросов.
fetch('http://example.com/api') .then(response => response.json()) .then(data => console.log(data));
Возврат такого объекта позволяет использовать другие функции, такие как Promise.All, которые могут выполнять несколько промисов и запускать один обратный вызов после их завершения.
Это огромный шаг вперед, но на самом деле это просто перемещение проблемы. Написание такого кода по-прежнему противоречит здравому смыслу, поскольку приходится управлять всеми запущенными промисами и следить за тем, чтобы все было в порядке. Если остальная часть вашего кода зависит от результата промиса, вам нужно переместить этот код в блок .then
или вызвать отдельную функцию с данными.
В идеале было бы лучше просто не возиться с промисами и обратными вызовами. Вы хотели бы написать такой код, но JavaScript либо остановит выполнение программы, либо запустит ее не по порядку.
doSomething(); var response = fetch('http://example.com/api'); console.log(response.json());
Но есть лучший способ — async/await. Вам все равно придется работать с промисами в конце дня, но async/await предлагает лучший синтаксис для их использования.
Чтобы использовать его, вам нужно указать функцию как функцию async
. Это гарантирует, что функция возвращает обещание, на которое JavaScript может воздействовать при вызове этой функции. Настоящая магия происходит с await
, который вы можете добавить перед промисом, чтобы сообщить движку JavaScript, что эта функция займет немного времени, и она должна приостановить вашу асинхронную функцию до тех пор, пока она не вернется, освобождая время. выполнять другие действия и поддерживать работу приложения.
async function fetchAPI() { doSomething(); var response = await fetch('http://example.com/api'); console.log(response.json()); } fetchAPI();
Теперь все в асинхронном блоке работает по порядку, но не останавливает выполнение программы для этого. Все, что идет после fetchAPI()
, все равно будет выполняться не по порядку, так как fetchAPI()
просто запускает выполнение асинхронной функции.
По сути, вы можете думать о await
как о чем-то, что вы будете добавлять перед веб-запросами и другими вещами, которые требуют времени для возврата ответа. Его можно использовать только в асинхронной функции, и вы используете его для явного ожидания функции, которая возвращает обещание, а не для вызова .Then()
и передачи обратного вызова.
Async/Await на других языках
Async/Await — это не просто концепция JavaScript; это функция многих других языков программирования, хотя точная реализация может немного отличаться.
Например, в C# есть задачи, которые функционируют как обещания и представляют собой асинхронную операцию, которая что-то возвращает. Вы можете ожидать других задач внутри асинхронной функции, что позволяет использовать неблокирующий код для таких операций, как выборка веб-запросов и запись/чтение с диска или внешних хранилищ данных, таких как корзины S3.
Вы можете связать их вместе, используя .ContinueWith(callback)
:
В зависимости от вашего приложения вам, возможно, придется неоднократно проверять в основном потоке, была ли задача выполнена. Например, у вас может быть сопрограмма, которая запускается один раз для каждого кадра и проверяет завершение задачи с помощью поля .IsCompleted
. Если это не так, он уступает до следующего кадра, а если это так, он может продолжать обработку синхронно.