> Почему нельзя просто вернуть Promise.resolve с промисом внутри в реализации any? (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Яндекс

Стек: JavaScript

> Пример ответа

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

Promise.resolve не отменяет и не прерывает уже запущенные промисы. В реализации any нужно дождаться первого успешного результата, но при этом все промисы уже запущены параллельно. Promise.resolve лишь создаёт новый resolved промис, но не останавливает выполнение остальных. Для корректной работы any требуется отслеживать состояние каждого промиса и собирать ошибки, что невозможно сделать простым Promise.resolve.

Подробное объяснение

Promise.any принимает массив промисов и возвращает первый успешно разрешённый. Если просто вернуть Promise.resolve(promise), то:

  • Мы не можем узнать, какой промис завершился первым успешно - Promise.resolve просто оборачивает значение, не отслеживая конкуренцию.
  • Все промисы уже запущены до вызова Promise.resolve, и их выполнение не контролируется.
  • При отклонении всех промисов нужно вернуть AggregateError, а для этого необходимо собирать ошибки от каждого - Promise.resolve этого не делает.
  • Promise.resolve не предоставляет механизма для отмены или игнорирования остальных промисов после первого успеха.

Реализация any требует:

  1. Запустить все промисы параллельно.
  2. Отслеживать первый успешный результат.
  3. Собирать все ошибки, если все промисы отклонены.
  4. Вернуть AggregateError при полном отклонении.

Promise.resolve решает только задачу обёртки значения в промис, но не управляет конкурентным выполнением.

На практике

В реальном коде Promise.any уже реализован в современном JavaScript (ES2021). Но если бы мы писали полифилл, то типичная ошибка - попытка использовать Promise.resolve для "обёртывания" каждого промиса. Это не работает, потому что:

  • Промисы уже выполняются, и их результаты приходят асинхронно.
  • Нужно явно обрабатывать состояния settled/rejected.
  • Для сбора ошибок требуется массив или счётчик.

Правильный подход - использовать new Promise с явным управлением resolve/reject, либо комбинацию Promise.allSettled с фильтрацией.

Пример кода

JAVASCRIPT
// Неправильно - не работает как any
function badAny(promises) {
return Promise.resolve(promises[0]); // возвращает только первый промис, не ждёт успеха
}
// Правильная упрощённая реализация
function myAny(promises) {
return new Promise((resolve, reject) => {
if (promises.length === 0) {
reject(new AggregateError([], 'All promises were rejected'));
return;
}
let rejectedCount = 0;
const errors = [];
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => resolve(value),
error => {
errors[index] = error;
rejectedCount++;
if (rejectedCount === promises.length) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
}
);
});
});
}

Как отвечать на собеседовании

Начни с ключевой проблемы: Promise.resolve не управляет конкурентным выполнением. Объясни, что any требует ожидания первого успеха среди множества параллельных промисов, а Promise.resolve просто оборачивает значение. Приведи пример неправильного подхода и покажи корректную реализацию через new Promise. Упомяни, что в реальном коде используем встроенный Promise.any. Будь готов обсудить AggregateError и отличие от Promise.race.

Что проверяет интервьюер

  • Понимание асинхронности и event loop в JavaScript.
  • Знание методов Promise: all, race, any, allSettled.
  • Умение реализовать конкурентный паттерн вручную.
  • Понимание разницы между обёрткой значения и управлением состоянием промисов.
  • Способность объяснить, почему простая обёртка не решает задачу.

Типичные ошибки

  • Путать Promise.resolve с отменой или прерыванием выполнения.
  • Думать, что Promise.resolve(promise) как-то "выбирает" первый успешный.
  • Не учитывать необходимость сбора ошибок для AggregateError.
  • Предлагать Promise.race как замену - он завершается при первом settled (любом), а any только при первом fulfilled.
  • Забывать обработать пустой массив промисов.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью