← Назад к вопросам

Возможно ли одновременное выполнение двух Promise?

1.3 Junior🔥 71 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Возможно ли одновременное выполнение двух Promise

Да, возможно! И это один из самых мощных паттернов в асинхронном JavaScript. Давайте разберёмся, как это работает и как это использовать правильно.

Базовая концепция

Promise выполняются независимо. Если вы создаёте два Promise, они начнут выполняться параллельно (в смысле асинхронного выполнения):

// Оба запроса стартуют одновременно
const promise1 = fetch('https://api.example.com/users');
const promise2 = fetch('https://api.example.com/posts');

// Оба запроса выполняются параллельно
// Они НЕ ждут друг друга

Последовательное vs Параллельное выполнение

Плохо — Последовательное (время: ждём A, потом B)

// Это СЕРИЙНОЕ выполнение
async function getDataSequential() {
  const users = await fetch('/api/users').then(r => r.json());
  // Ждём 1 сек
  
  const posts = await fetch('/api/posts').then(r => r.json());
  // Ещё ждём 1 сек
  
  // Итого: 2 секунды
  return { users, posts };
}

Хорошо — Параллельное (время: A и B выполняются одновременно)

// Способ 1: Promise.all() — самый популярный
async function getDataParallel() {
  const [users, posts] = await Promise.all([
    fetch('/api/users').then(r => r.json()),
    fetch('/api/posts').then(r => r.json())
  ]);
  // Итого: 1 секунда (оба запроса идут параллельно)
  return { users, posts };
}

// Способ 2: Создать Promise сразу, затем await
async function getDataParallel2() {
  const usersPromise = fetch('/api/users').then(r => r.json());
  const postsPromise = fetch('/api/posts').then(r => r.json());
  // Обе request уже запущены!
  
  const users = await usersPromise;
  const posts = await postsPromise;
  // Итого: 1 секунда
  return { users, posts };
}

Promise.all() — Ждёт все Promise

const results = await Promise.all([
  promise1,
  promise2,
  promise3
]);

Особенности:

  • Ждёт, пока все Promise resolve
  • Если любой Promise reject — выбрасывает ошибку
  • Возвращает массив результатов в том же порядке
const numbers = await Promise.all([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3)
]);
// numbers = [1, 2, 3]

// Если один promise reject
const failed = await Promise.all([
  Promise.resolve(1),
  Promise.reject('Error!'),
  Promise.resolve(3)
]);
// Выбрасит Error, остальное игнорируется

Promise.allSettled() — Ждёт все, но не выбрасывает ошибку

const results = await Promise.allSettled([
  Promise.resolve(1),
  Promise.reject('Error!'),
  Promise.resolve(3)
]);

// Результат:
// [
//   { status: 'fulfilled', value: 1 },
//   { status: 'rejected', reason: 'Error!' },
//   { status: 'fulfilled', value: 3 }
// ]

// Используй, когда все Promise важны, даже если некоторые fail

Promise.race() — Первый, кто завершится

const fastest = await Promise.race([
  fetch('https://cdn1.com/image.jpg'),
  fetch('https://cdn2.com/image.jpg'),
  fetch('https://cdn3.com/image.jpg')
]);
// Вернёт результат первого завершённого Promise

// Пример с timeout
const resultOrTimeout = await Promise.race([
  fetch('/api/data'),
  new Promise((_, reject) => 
    setTimeout(() => reject('Timeout!'), 5000)
  )
]);

Promise.any() — Первый успешный

const firstSuccess = await Promise.any([
  Promise.reject('Failed 1'),
  Promise.resolve('Success!'),
  Promise.reject('Failed 2')
]);
// Вернёт 'Success!' (первый resolve)

// Если все reject
const allFailed = await Promise.any([
  Promise.reject('Error 1'),
  Promise.reject('Error 2')
]);
// Выбросит AggregateError

Практические примеры

Загрузка нескольких ресурсов

async function loadPage() {
  const [user, settings, recommendations] = await Promise.all([
    fetch('/api/user').then(r => r.json()),
    fetch('/api/settings').then(r => r.json()),
    fetch('/api/recommendations').then(r => r.json())
  ]);
  
  return { user, settings, recommendations };
}

Обработка ошибок с allSettled

async function sendNotifications(userIds: string[]) {
  const promises = userIds.map(id => 
    fetch(`/api/notify/${id}`, { method: 'POST' })
  );
  
  const results = await Promise.allSettled(promises);
  
  const failed = results.filter(r => r.status === 'rejected');
  const succeeded = results.filter(r => r.status === 'fulfilled');
  
  console.log(`Sent to ${succeeded.length}, failed for ${failed.length}`);
}

Timeout для Promise

function withTimeout<T>(
  promise: Promise<T>,
  ms: number
): Promise<T> {
  return Promise.race([
    promise,
    new Promise<T>((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), ms)
    )
  ]);
}

const data = await withTimeout(
  fetch('/api/data').then(r => r.json()),
  5000 // 5 секунд
);

Выполнение в батчах (не все сразу, чтобы не перегружать сервер)

async function processBatch<T>(
  items: T[],
  processor: (item: T) => Promise<void>,
  batchSize: number = 5
) {
  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    // Выполнить 5 Promise параллельно
    await Promise.all(batch.map(processor));
    // Потом следующий батч
  }
}

await processBatch(
  userIds,
  async (id) => {
    await fetch(`/api/process/${id}`, { method: 'POST' });
  },
  5 // 5 одновременно
);

Когда использовать каждый метод

МетодИспользуй когдаПример
Promise.all()Все Promise важны и должны успешно выполнитьсяЗагрузка data для страницы
Promise.allSettled()Некоторые могут fail, но нужны все результатыОтправка нескольких уведомлений
Promise.race()Нужен первый результатTimeout, выбор самого быстрого сервера
Promise.any()Нужен первый успешный результатBackup API endpoints

Распространённые ошибки

Ошибка 1: Await в цикле вместо Promise.all

// ПЛОХО -- последовательно
for (const id of userIds) {
  const user = await fetch(`/api/user/${id}`); // Медленно!
}

// ХОРОШО -- параллельно
const users = await Promise.all(
  userIds.map(id => fetch(`/api/user/${id}`))
);

Ошибка 2: Забыть создать Promise перед await

// ПЛОХО -- второй fetch начинается только после первого
const user = await fetch('/api/user');
const posts = await fetch('/api/posts');

// ХОРОШО -- оба fetch стартуют одновременно
const userPromise = fetch('/api/user');
const postsPromise = fetch('/api/posts');
const user = await userPromise;
const posts = await postsPromise;

Заключение

Да, два (или несколько) Promise очень просто выполняются параллельно. Это достигается через:

  • Promise.all() — для критичных данных
  • Promise.allSettled() — если некоторые могут fail
  • Promise.race() — для timeout и первого результата
  • Promise.any() — для первого успешного

Использование параллельного выполнения критично для производительности приложения. Всегда думай: могу ли я запустить эти операции одновременно?