Promise.all возвращает промис, который отклоняется при отклонении любого из переданных all обещаний. Например следующий код:
const a = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("resolve 1");
resolve(1);
}, 2000);
});
const b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("reject 2");
reject(2);
}, 1000);
});
const c = new Promise((resolve, reject) => {
console.log("resolve");
resolve(3);
});
Promise.all([a, b, c]).then(
r => {
console.log(r);
},
() => {
console.log("err");
},
);
выведет
resolve 3
reject 2
err
resolve 1
т.е. все завершилось без ожидания завершения промиса a (resolve 1 выводится после err). Вопрос в том, как дождаться, пока все промисы будут выполнены и/или отклонены?
Очень просто: замаскировать ошибку через вызов catch
.
const a = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("resolve 1");
resolve(1);
}, 2000);
});
const b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("reject 2");
reject(2);
}, 1000);
});
const c = new Promise((resolve, reject) => {
console.log("resolve 3");
resolve(3);
});
Promise.all([a, b, c].map(p => p.catch(x => console.error(x)))).then(
r => {
console.log(r);
}
);
Результат: [1, undefined, 3].
Вот как-то так получилось (не знаю на сколько это говнокод), я сделал функцию, которая модифицирует промисы, добавляя им свойство isPending
, в методе waitForAll
я каждому промису добавляю обработчики в then
, в которых при успешном/неуспешном выполнени промиса пробегаю входной массив и проверяю, у всех ли промисов в масиве isPending == false
, если так, значит все промисы уже завершились.
const a = MakePromise(new Promise((resolve, reject) => {
setTimeout(() => {
console.log("resolve 1");
resolve(1);
}, 2000);
}));
const b = MakePromise(new Promise((resolve, reject) => {
setTimeout(() => {
console.log("reject 2");
reject(2);
}, 1000);
}));
const c = MakePromise(new Promise((resolve, reject) => {
console.log("resolve");
resolve(3);
}));
waitForAll([a, b, c]);
function waitForAll(arr) {
arr.forEach((p) => {
p.then(
(r) => {
if (allDone(arr)) console.log('all done');
},
(e) => {
if (allDone(arr)) console.log('all done');
});
});
};
function allDone(arr) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].isPending()) return false;
}
return true;
};
function MakePromise(promise) {
var isPending = true;
var result = promise.then(
(v) => {
isPending = false;
return v;
},
(e) => {
isPending = false;
throw e;
}
);
result.isPending = () => {
return isPending;
};
return result;
}
Я понял что предыдущий вариант явно не очень, сделал через каунтер, тоесть функция waitForAll
получает массив промисов, сразу записываем в переменную длину массива (количество промисов) и в обработчиках then
уменьшаем ету переменную ну и сравниваем ее с 0
, тоесть если количество 0, значит все промисы выполнены :
const a = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("resolve 1");
resolve(1);
}, 2000);
});
const b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("reject 2");
reject(2);
}, 1000);
});
const c = new Promise((resolve, reject) => {
console.log("resolve");
resolve(3);
});
waitForAll([a, b, c]);
function waitForAll(arr) {
var count = arr.length;
arr.forEach((p) => {
p.then(
(r) => {
count--;
if (count == 0) console.log('all done');
},
(e) => {
count--;
if (count == 0) console.log('all done');
});
});
};
const a = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("resolve 1");
resolve(1);
}, 2000);
});
const b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("reject 2");
reject(2);
}, 1000);
});
const c = new Promise((resolve, reject) => {
console.log("resolve");
resolve(3);
});
Promise.all([a, b, c].map(p => p.then(
x => ({ resolved: x }),
e => ({ rejected: e })
))).then(results => {
console.log('=== ALL ===');
for (var res of results) {
if ('resolved' in res) { // Not res.resolved because `resolve(0)`
console.log(res.resolved);
} else {
console.log('error', res.rejected);
}
}
});
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Допустим есть событие scroll $(window)scroll(function() { следящее за прокруткой
Разбираю файл JSON с помощью JSONparse(); Выясняется такая вещь, что ключ с дефисом не работает
Возникла проблема с запуском node js серверной части на удаленном хостинге