Обходите вход через for…of, сохраняя индекс каждого элемента. Счётчик с начальной единицей учитывает завершение самого обхода, включая пустой iterable.
Создание собственной версии Promise.all
Обходите вход через for…of, сохраняя индекс каждого элемента. Счётчик с начальной единицей учитывает завершение самого обхода, включая пустой iterable.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Реализуйте функцию, которая воспроизводит поведение встроенного Promise.all. Функция принимает массив (или любой итерируемый объект) с промисами или обычными значениями и возвращает новый промис. Этот промис переходит в состояние fulfilled, когда все переданные элементы успешно завершились, и в состояние rejected при первой ошибке. Позиция элементов в результирующем массиве должна соответствовать их порядку во входных данных.
Ответ
Обходите вход через for…of, сохраняя индекс каждого элемента. Счётчик с начальной единицей учитывает завершение самого обхода, включая пустой iterable.
function all(iterable) {
return new Promise((resolve, reject) => {
const result = [];
let remaining = 1, index = 0;
for (const item of iterable) {
const position = index++;
remaining++;
Promise.resolve(item).then(value => {
result[position] = value;
if (--remaining === 0) resolve(result);
}, reject);
}
if (--remaining === 0) resolve(result);
});
}
Подойдут массив, Set или генератор. Неитерируемый объект либо ошибка итератора отклонят итоговый Promise через исключение в executor. Порядок результатов сохраняется. Это аналог основного поведения, без полной поддержки произвольных конструкторов Promise и отмены операций.