3

So I need to do something like:

promiseFunction1().then((result) => {

}).catch((err) => {
    // handle err
});

promiseFunction2().then((result) => {

}).catch((err) => {
    // handle err
});

....

promiseFunctionN().then((result) => {

}).catch((err) => {
    // handle err
});

// WAIT FOR BOTH PROMISES TO FINISH
functionWhenAllPromisesFinished();

I cannot use Promise.all, as I DO NOT CARE IF ONE or ALL OF THEM FAIL. I need to be sure that ALL promises have finished. Also, the callback functions in then() are quite unique to each of the promiseFunctionX().

I am sure this is somewhat trivial, but I cannot figure it out. My initial idea was to keep a counter in the upper scope of running promises and incrementing it when one is run and decrementing it in finally(). Then I would need some async function checkIfRunningPromisesAre0() , but I am not sure how to implement this either, as it looked like recursion hell.

Here is my sample, but consider it just a material to laugh at poor implementation:

async function RunningPromisesFinished(){
    if(RunningPromises > 0){
        await sleep(2000);
        return await RunningPromisesFinished();
    }else{
        return true;
    }
}

on top of that Id have to implement async function sleep(N) and in few seconds the recursion level would be high, which im sure is not good for RAM.

michnovka
  • 2,880
  • 3
  • 26
  • 58
  • 1
    Promise.all is resolved when all the promises are resolved, that pretty much solves your problem. If you don't want to do something with the exception just let it be! – Mehul Mittal Jun 21 '19 at 12:08
  • 1
    `createSomePromise().catch(()=>doSomething())` will ***always*** return a promise that cannot reject (unless you do something stupid in the `catch` handler). This means that your presumption that you can't use `Promise.all` here is incorrect. – spender Jun 21 '19 at 12:14

2 Answers2

5

Collect all the promises:

  const promise1 = promiseFunction1().then((result) => {
   }).catch((err) => {
     // handle err
   });

Then you can use Promise.all on them:

  await Promise.all([promise1, promise2, /*...*/ ]);

I cannot use Promise.all, as I DO NOT CARE IF ONE or ALL OF THEM FAIL

For sure you can. As you added a .catch to each promise that gets the promise chain back into the resolution branch, promise1 will never reject, therefore Promise.all will never reject too.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • Thanks for quick reply. So what would be the results array for item on position of promise that errored and was consumed by its catch()? – michnovka Jun 21 '19 at 12:14
  • 1
    @michnovka whatever you returned from the `.catch` callback. – Jonas Wilms Jun 21 '19 at 12:14
  • @michnovka Interestingly enough, I just saw an article about some v8 updates and there is currently a proposal for a `Promise.allSettled` method that will resolve once all promises have resolved or rejected. [Here's the proposal on Github](https://github.com/tc39/proposal-promise-allSettled). – Ace Jun 21 '19 at 13:02
  • Until `Promise.allSettled()` is fully implemented, [here's a solution](https://stackoverflow.com/a/31424853/3478010). – Roamer-1888 Jun 21 '19 at 18:08
3

You could use the Promise.allSettled method:

The Promise.allSettled() method returns a promise that resolves after all of the given promises have either resolved or rejected, with an array of objects that each describe the outcome of each promise.

As this is relatively new, it might not be supported by the majority of browsers yet. Here is a polyfill:

 function allSettled(promises) {
    let wrappedPromises = promises.map(p => 
      Promise.resolve(p)
        .then(
           val => ({ status: 'fulfilled', value: val }),
           err => ({ status: 'rejected', reason: err })
        )
    );
    return Promise.all(wrappedPromises);
 }
yashhy
  • 2,856
  • 5
  • 31
  • 57
Vadim Hulevich
  • 1,803
  • 8
  • 17