0

Given an array of Promises, and a Promise.all() statement, if one of the promises fails, the entire chain stops (it doesn't wait for any subsequent Promises to fulfill) and Promise.all().catch() fires, but Promise.all().then() does not.

However, if the individual Promises have their own 'catch' blocks, and if whatever problem caused the Promise to fail can be fixed within that catch block, how can we prevent the rest of the promises from being ignored/failing, so that Promises.all().then() will still execute? Is there some way to "negate" the error from within the .catch() block, so Promises.all() doesn't see it? I tried return Promise.resolve() at the end of the .catch() block, but it doesn't work.

Example:

let promise_array = [];

let p = somePromisyFunction1()
    .then(() => { // Do something good })
    .catch(() => { // Handle the bad });
promise_array.push(p);

p = somePromisyFunction2()
    .then(() => { // Do something good })
    .catch(() => { // Handle the bad });
promise_array.push(p);

p = somePromisyFunction3()
    .then(() => { // Do something good })
    .catch(() => { // Handle the bad });
promise_array.push(p);


// ...
// More Promisy functions added to promise_array here...
// ...

Promise.all(promise_array)
    .then(() => { // We're all done! All promises fulfilled. })
    .catch(() => { // Something went wrong! });

In this example, if any one of the somePromisyFunctionX() fails, that function's .catch() clause will execute, and then the Promise.all.catch() clause will also immediately execute, without waiting for any of the subsequent promises to fulfill.

However, if we can fix whatever bad thing happened, within the individual function's .catch() clause, how can we prevent Promises.all().catch() from being immediately triggered, and instead allowing that the rest of the promises can go ahead and fulfill? In some way, in the .catch() clause, can we "negate" the error, so it looks like the promise actually fulfilled successfully instead of appearing to fail?

I can do this in an async/await function using try/catch blocks, but not sure how to do it with .then/.catch.

Ryan Griggs
  • 2,457
  • 2
  • 35
  • 58
  • 2
    Your basic assertion is incorrect. If you have `.catch()` handlers, `Promise.all()` will not behave that way. – Pointy Dec 07 '20 at 15:07
  • [Your code seems fine](https://jsbin.com/gituguxato/edit?js,console). Can you give an example where you're getting a failure? – VLAZ Dec 07 '20 at 15:10
  • 1
    `Promise.allSettled` just waits for all promises to settle, regardless of the result. – Shankar Ganesh Jayaraman Dec 07 '20 at 15:11
  • Please show us what exactly your "`// Handle the bad`*" does and provide a [mcve] – Bergi Dec 07 '20 at 15:42
  • Maybe what you're actually doing is `const p = somePromisyFunction1(); promise_array.push(p); p.catch(() => { … });`? ` – Bergi Dec 07 '20 at 15:44

1 Answers1

1

Yes, all you need to do is return something from the catch of the failed promise and it will be "recovered" as a resolve in the Promise.all

Hopefully this demonstrates. Without the catch in somePromisyFunction2 the whole chain will fail (check by commenting it out) but with it the whole chain succeeds with the recovered value

let promise_array = [];

let p = somePromisyFunction1()
    //.then(() => { // Do something good })
   // .catch(() => { // Handle the bad });
promise_array.push(p);

p = somePromisyFunction2()
    //.then(() => { // Do something good })
    .catch((v) => "2 - " + v);
promise_array.push(p);

p = somePromisyFunction3()
    //.then(() => { // Do something good })
    //.catch(() => { // Handle the bad });
promise_array.push(p);


// ...
// More Promisy functions added to promise_array here...
// ...

Promise.all(promise_array)
    .then((v) => { console.log("all good",v) })
    .catch(() => { console.log("something bad") });
    
    
function somePromisyFunction1(){
  return new Promise(resolve => resolve("1"));
}

function somePromisyFunction2(){
  return new Promise((resolve,reject) => reject("oh no something went wrong!"));
}


function somePromisyFunction3(){
  return new Promise(resolve => resolve("3"));
}

You could also choose to use allSettled instead of all and then you can handle the failures inline

let promise_array = [];

let p = somePromisyFunction1()
    //.then(() => { // Do something good })
   // .catch(() => { // Handle the bad });
promise_array.push(p);

p = somePromisyFunction2()
    //.then(() => { // Do something good })
    //.catch((v) => "2 - " + v);
promise_array.push(p);

p = somePromisyFunction3()
    //.then(() => { // Do something good })
    //.catch(() => { // Handle the bad });
promise_array.push(p);


// ...
// More Promisy functions added to promise_array here...
// ...

Promise.allSettled(promise_array)
    .then((v) => { console.log("all good",v) })
    .catch(() => { console.log("something bad") });
    
    
function somePromisyFunction1(){
  return new Promise(resolve => resolve("1"));
}

function somePromisyFunction2(){
  return new Promise((resolve,reject) => reject("oh no something went wrong!"));
}


function somePromisyFunction3(){
  return new Promise(resolve => resolve("3"));
}
Jamiec
  • 133,658
  • 13
  • 134
  • 193