Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как выполнить несколько асинхронных операций параллельно

Короткий ответ

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 — Ждёт завершения всех промисов и сообщает результат каждого — успех или ошибку.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.