How to gracefully determine when all Promises are rejected?

How can I execute a function when all Promises have been rejected ? I think Promise.all is not suitable unless I reject Promises instead of resolving them. But it would be logical to do this in my situation and, thus, make the code more complex. I would like to use a similar syntax like prom.all. Since I believe that such a syntax is very easy to use.

// some promises to play with
let promise1 = new Promise((resolve, reject) => {setTimeout(resolve, 100)});

let promise2 = new Promise((resolve, reject) => {setTimeout(resolve, 100)});

let promise3 = new Promise((resolve, reject) => {setTimeout(resolve, 100)});

let promise4 = new Promise((resolve, reject) => {setTimeout(reject, 100)});

let promise5 = new Promise((resolve, reject) => {setTimeout(reject, 100)});

// run code (on .then) if all promises are resolved
Promise.all([promise1, promise2, promise3])
  .then(() => console.log('1: all promises have been resolved'))
  .catch(() => console.log('1: one or more promises have been rejected'));

// run code (on .catch) if one or more promises are rejected
Promise.all([promise1, promise2, promise4])
  .then(() => console.log('2: all promises have been resolved'))
  .catch(() => console.log('2: one or more promises have been rejected'));

// the issue:
// run code if one or more promises are resolved
//
// How can I execute a function when all 
// promises have been rejected?
// I think Promise.all isn't 
// suited, unless I reject the promises instead of 
// resolving them. But it would not be logical to do 
// that in my situation, 
// and thus make the code trickier to follow
// I would like to use a similar syntax
// as promise.all.

// these promises should return '3: one or more promises have been resolved' and '4: all promises have been rejected'
Promise.all([promise2, promise4])
  .then(() => console.log('3: one or more promises have been resolved'))
  .catch(() => console.log('3: all promises have been rejected'));
  
  Promise.all([promise5, promise4])
  .then(() => console.log('4: one or more promises have been resolved'))
  .catch(() => console.log('4: all promises have been rejected'));
Run codeHide result
+4
source share
3 answers
[promise1, promise2, promise3 /*...*/]
 .reduce((chain, promise) => chain.catch(() => promise))
 .catch(() => console.error("all failed"));

This creates a chain of promises.

+2
source

Try to promise - any npm module or the equivalent of bluebird. You can stop when at least one promise has been resolved or failed if not resolved:

Promise.any([....])
.then(() => "bad, at least one resolved"), () => "good, all rejected")
0

If I understand correctly, you want to run the function if and only if all the promises are rejected, and you want something as elegant as it is Promise.all()right ..? Then you can use Promise.all(), but you need a little helper function for invertpromises.

var invert = pr => pr.then(v => Promise.reject(v), x => Promise.resolve(x));

Now your three deviation promises will do what you want.

var promises = [new Promise((resolve, reject) => {setTimeout(reject, 100, "1st promise rejected")}),
                new Promise((resolve, reject) => {setTimeout(reject, 100, "2nd promise rejected")}),
                new Promise((resolve, reject) => {setTimeout(reject, 100, "3rd promise rejected")})],
    invert   = pr => pr.then(v => Promise.reject(v), x => Promise.resolve(x));

Promise.all(promises.map(invert))
       .then(errs => errs.forEach(err => console.log(err)));
Run codeHide result

If any of your promises is resolved in some way, you can catch the resolution at the stage catchif you want.

0
source

Source: https://habr.com/ru/post/1692376/


All Articles