Выбор ответа Middle Реализация с нуля спрашивают часто обновлено

Ошибка порядка в своём Promise.all

Вопрос

В чём главная ошибка этой реализации Promise.all?

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    promises.forEach((p) => {
      Promise.resolve(p).then((value) => {
        results.push(value);
        if (results.length === promises.length) resolve(results);
      }, reject);
    });
  });
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Результаты идут в порядке завершения, а не входа; пустой массив не завершится. push кладёт значения по мере готовности, и быстрый второй промис окажется первым.

Варианты ответа

  1. reject нельзя передавать вторым аргументом then: ошибка уйдёт мимо промиса
  2. Promise.resolve(p) лишний: он оборачивает промис повторно и ломает его значение
  3. Ошибок нет: реализация совпадает со стандартной и работает на любом массиве
  4. Результаты идут в порядке завершения, а не входа; пустой массив не завершитсяправильный ответ

Разбор

push кладёт значения по мере готовности, и быстрый второй промис окажется первым. Нужно писать по индексу results[i] = value и считать завершённые отдельным счётчиком (проверка length по массиву с индексами тоже сломается: если последний по индексу элемент завершится раньше остальных, длина сразу станет полной). Для пустого массива forEach не выполнится ни разу, resolve не вызовется, а настоящий Promise.all([]) сразу выполняется пустым массивом. reject во втором аргументе then корректен, а Promise.resolve нужен, чтобы принимать и не-промисы.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.