#javascript #promise
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). Вопрос в том, как дождаться, пока все промисы будут выполнены и/или отклонены?
Ответы
Ответ 1
Очень просто: замаскировать ошибку через вызов 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].Ответ 2
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); } } });Ответ 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'); }); }); };
Комментариев нет:
Отправить комментарий