Страницы

Поиск по вопросам

воскресенье, 1 декабря 2019 г.

Как дождаться выполнения нескольких Promise аналогично Promise.all

#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'); }); }); };

Комментариев нет:

Отправить комментарий