[Medium] 📄 Async/Await
💡 Рекомендуется: сначала прочитайте Promise для понимания основных концепций.
Что такое async/await?
async/await — это синтаксический сахар, введённый в ES2017 (ES8), построенный поверх Promise.
Он позволяет писать асинхронный код, который выглядит как синхронный, что улучшает читаемость и сопровождаемость.
Основные концепции:
- Функция
asyncвсегда возвращает Promise. awaitможно использовать только внутри функцииasync.awaitприостанавливает выполнение функции до завершения Promise.
Базовый синтаксис (Базовый синтаксис)
Функция async
Ключевое слово async автоматически заставляет функцию возвращать Promise:
// Традиционный стиль Promise
function fetchData() {
return Promise.resolve('data');
}
// Стиль async (эквивалентен)
async function fetchData() {
return 'data'; // автоматически оборачивается как Promise.resolve('data')
}
// одинаковый паттерн вызова
fetchData().then((data) => console.log(data)); // 'data'
Ключевое слово await
await ожидает Promise и возвращает его resolved-значение:
async function getData() {
const result = await Promise.resolve('done');
console.log(result); // 'done'
}
Promise vs async/await
Пример 1: простой API-запрос
Стиль Promise:
function getUserData(userId) {
return fetch(`/api/users/${userId}`)
.then((response) => response.json())
.then((user) => {
console.log(user);
return user;
})
.catch((error) => {
console.error('Error:', error);
throw error;
});
}
Стиль async/await:
async function getUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
const user = await response.json();
console.log(user);
return user;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
Пример 2: цепочка нескольких асинхронных операций
Стиль Promise:
function processUserData(userId) {
return fetchUser(userId)
.then((user) => {
return fetchPosts(user.id);
})
.then((posts) => {
return fetchComments(posts[0].id);
})
.then((comments) => {
console.log(comments);
return comments;
})
.catch((error) => {
console.error('Error:', error);
});
}
Стиль async/await:
async function processUserData(userId) {
try {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
console.log(comments);
return comments;
} catch (error) {
console.error('Error:', error);
}
}
Обработка ошибок (Error Handling)
try/catch vs .catch()
Использование try/catch с async/await:
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Запрос не удался:', error);
// Здесь можно обрабатывать разные типы ошибок
if (error.name === 'NetworkError') {
// обработка сетевой ошибки
}
throw error; // повторный выброс или возврат запасного значения
}
}
Смешанное использование (не рекомендуется, но работает):
async function fetchData() {
const response = await fetch('/api/data').catch((error) => {
console.error('Запрос не удался:', error);
return null;
});
if (!response) return null;
const data = await response.json();
return data;
}