В предыдущей части руководства хорошо видно, что обещания (promises) и использование then для обработки асинхронных действий легче для понимания, чем пирамида обратных вызовов (callback). ECMAScript 2016 (ES7) предлагает функцию async и ключевое слово await.
Асинхронные функции с async/await
Функция async позволяет обрабатывать асинхронный код таким образом, чтобы он выглядел синхронным. Функция async под капотом по-прежнему использует обещания (promise), но имеет более традиционный JavaScript-синтаксис. В этом разделе рассмотрим примеры этого синтаксиса.
Для создания функции async, достаточно добавить ключевое слово async перед функцией:
// Асинхронная функция
async function getUser() {
return {}
}
Хотя эта функция ещё не обрабатывает ничего асинхронного, её поведение отличается от традиционной функции. Если вы выполните функцию, вы обнаружите, что она вместо значения возвращает обещание с [[PromiseStatus]] и [[PromiseValue]]. Попробуйте залогировать вызов функции getUser:
console.log(getUser())
Вернётся следующее:
__proto__: Promise
[[PromiseStatus]]: "fulfilled"
[[PromiseValue]]: Object
Это означает, что вы можете обрабатывать функцию async с помощью then так же, как и обещание (promise). Попробуйте это с помощью следующего кода:
getUser().then(response => console.log(response))
Такой вызов getUser передаёт возвращаемое значение анонимной функции, которая записывает значение в консоль. При выполнении этого кода получите следующее:
{}
Функция async может обрабатывать обещание (promise), вызываемое в ней, с помощью оператора await. await может использоваться с функцией async и, перед выполнением назначенного кода, будет ждать, пока обещание не установится.
Запрос fetch из предыдущего раздела можно переписать следующим образом с помощью async/await:
// Обработка fetch с помощью async/await
async function getUser() {
const response = await fetch('https://api.github.com/users/octocat')
const data = await response.json()
console.log(data)
}
// запуск
getUser()
Здесь оператор await гарантирует, что данные не попадут в консоль раньше, чем их вернёт асинхронный запрос.
Теперь data можно обрабатывать внутри функции getUser без использования then. Результат, который попадёт в консоль:
login: "octocat",
id: 583231,
avatar_url: "https://avatars3.githubusercontent.com/u/583231?v=4"
blog: "https://github.blog"
company: "@github"
followers: 3203
...
Примечание. Во многих средах режим
asyncнеобходим для использованияawait, однако некоторые новые версии браузеров и Node разрешают использоватьawaitверхнего уровня, что позволяет обойтись без создания функцииasyncдля завершения ожидания.
Наконец, поскольку в асинхронной функции обрабатывается выполненное обещание (promise), можно легко обрабатывать ошибку внутри этой функции. В этом случае вместо использования методов catch и then для обработки исключения нужно использовать шаблон try/catch. Вот как это выглядит:
// Обработка успеха и ошибок с помощью async/await
async function getUser() {
try {
// Успешно в try
const response = await fetch('https://api.github.com/users/octocat')
const data = await response.json()
console.log(data)
} catch (error) {
// Ошибка в catch
console.error(error)
}
}
Теперь, если вернётся ошибка, будет выполнен код из блока catch, который запишет эту ошибку в консоль.
Современный асинхронный JavaScript-код легко обрабатывается с помощью синтаксиса async/await, но важно иметь практические знания о том, как работают обещания (promise), потому что у них есть дополнительные функции, которые нельзя обработать с помощью async/await. Например, объединение обещаний с помощью Promise.all().
Итог
Поскольку веб-API часто предоставляют данные асинхронно, изучение того, как обрабатывать результат асинхронных действий, является важной частью работы JavaScript-разработчика. В этой серии статей было рассмотрено, как используется цикл событий для обработки порядка выполнения кода со стеком и очередью. Были рассмотрены три способа обработки успеха или отказа асинхронного события с помощью обратных вызовов (callback), обещаний (promise) и синтаксиса async/await. Для обработки асинхронных действий использовался Fetch Web API.
Understanding the Event Loop, Callbacks, Promises, and Async/Await in JavaScript.



