async/await в JavaScript
async/await в JavaScript: как писать асинхронный код синхронным стилем, обработка ошибок через try/catch и параллельный запуск промисов.
async/await — синтаксический сахар над промисами. Ключевое слово
asyncперед функцией делает её асинхронной, аawaitвнутри неё «приостанавливает» выполнение до разрешения промиса — без явных.then.
async-функция
Функция с async всегда возвращает промис. Если она возвращает обычное значение, оно автоматически оборачивается в Promise.resolve.
async function greet() {
return 'Привет!';
}
greet().then(msg => console.log(msg)); // Привет!
console.log(greet()); // Promise { 'Привет!' }
Вывод:
Promise { 'Привет!' }
Привет!
await — ожидание промиса
await можно использовать только внутри async-функции. Он ждёт, пока промис разрешится, и возвращает его значение. Остальной код снаружи функции при этом не блокируется.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function loadData() {
console.log('Загрузка...');
await delay(500); // ждём 500 мс
console.log('Данные загружены');
return { items: [1, 2, 3] };
}
async function main() {
const data = await loadData();
console.log('Количество:', data.items.length);
}
main();
Вывод:
Загрузка... Данные загружены Количество: 3
Обработка ошибок через try/catch
Вместо .catch в цепочке промисов с async/await используют привычный try/catch. Если awaited-промис отклоняется, управление переходит в блок catch.
function fetchUser(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id === 1) resolve({ name: 'Аня' });
else reject(new Error('Пользователь не найден'));
}, 200);
});
}
async function showUser(id) {
try {
const user = await fetchUser(id);
console.log('Пользователь:', user.name);
} catch (err) {
console.log('Ошибка:', err.message);
} finally {
console.log('Запрос завершён');
}
}
showUser(1);
showUser(99);
Вывод:
Пользователь: Аня Запрос завершён Ошибка: Пользователь не найден Запрос завершён
Параллельное выполнение
Если написать два await подряд, запросы выполнятся последовательно (второй ждёт первого). Для параллельного запуска используют Promise.all.
function wait(ms, val) {
return new Promise(r => setTimeout(() => r(val), ms));
}
async function sequential() {
const a = await wait(300, 'A');
const b = await wait(300, 'B');
console.log(a, b); // ~600 мс суммарно
}
async function parallel() {
const [a, b] = await Promise.all([wait(300, 'A'), wait(300, 'B')]);
console.log(a, b); // ~300 мс суммарно
}
sequential();
parallel();
Вывод:
A B A B
Не делайте
awaitв циклеforEach— он не ждёт промисы. Используйтеfor...ofилиPromise.allс.map.
Коротко
asyncперед функцией делает её асинхронной; она всегда возвращает промис.awaitприостанавливает выполнение внутриasync-функции до разрешения промиса.- Ошибки обрабатывают через
try/catch/finally— так же, как в синхронном коде. - Для параллельного запуска нескольких промисов используйте
Promise.all.