Как выполнить несколько асинхронных операций параллельно
Короткий ответ
Promise.all() ждёт все промисы одновременно и возвращает массив результатов в том же порядке:
const delay = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
const start = Date.now();
const [user, orders] = await Promise.all([delay(300, 'Anna'), delay(300, 3)]);
console.log(user, orders);
console.log(Date.now() - start < 500 ? 'about 300 ms, not 600' : 'slow');Результат:
Anna 3
about 300 ms, not 600С fetch
То же с запросами: оба начинаются сразу:
const [user, orders] = await Promise.all([
fetch('/api/user').then((r) => r.json()),
fetch('/api/orders').then((r) => r.json()),
]);Если часть может упасть
Promise.all() падает, как только падает один промис. Promise.allSettled() дожидается всех и сообщает статус каждого:
const results = await Promise.allSettled([
Promise.resolve('photo 1'),
Promise.reject(new Error('photo 2 is too large')),
Promise.resolve('photo 3'),
]);
for (const result of results) {
console.log(result.status, result.value ?? result.reason.message);
}Результат:
fulfilled photo 1
rejected photo 2 is too large
fulfilled photo 3Частая ошибка
await в цикле выполняет операции по очереди. Если они не зависят друг от друга, это просто медленнее:
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const start = Date.now();
for (const ms of [200, 200, 200]) {
await delay(ms);
}
console.log(Date.now() - start >= 600 ? 'one by one: 600 ms' : 'fast');Результат:
one by one: 600 msФункции из этого ответа
- Promise.all — Ждёт выполнения всех промисов параллельно.
- Promise.allSettled — Ждёт завершения всех промисов и сообщает результат каждого — успех или ошибку.