Создайте общий Promise и счётчик незавершённых входов. Каждый результат записывается по исходному индексу; первый rejection отклоняет общий Promise.
Самописный полифил для Promise.all
Создайте общий Promise и счётчик незавершённых входов. Каждый результат записывается по исходному индексу; первый rejection отклоняет общий Promise.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Напишите функцию promiseAll, имитирующую поведение встроенного Promise.all. Функция должна принимать массив промисов и возвращать новый промис, который будет выполнен успешно только когда выполнятся все переданные промисы, а в случае отклонения любого из них – сразу отклонится с тем же значением. Порядок результатов в массиве должен соответствовать порядку элементов входного массива.
function promiseAll(tasks: Promise<any>[]): Promise<any[]> {
// ваш код тут
}
Ответ
Создайте общий Promise и счётчик незавершённых входов. Каждый результат записывается по исходному индексу; первый rejection отклоняет общий Promise.
function promiseAll(tasks) {
return new Promise((resolve, reject) => {
const values = Array(tasks.length);
let remaining = tasks.length;
if (!remaining) { resolve(values); return; }
for (let index = 0; index < tasks.length; index++) {
Promise.resolve(tasks[index]).then(value => {
values[index] = value;
if (--remaining === 0) resolve(values);
}, reject);
}
});
}
Пустой массив разрешается в []. Promise.resolve также принимает обычные значения и thenable. Цикл по индексам не зависает на дырках массива, как forEach: они становятся undefined. Уже запущенные операции не отменяются при ошибке. Это реализация контракта массива, не полный generic-polyfill для произвольного iterable и подклассов Promise.