michnovka
michnovka

Reputation: 3419

How to run concurrent promises in JS and then wait for them to finish without Promise.all()?

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.

Upvotes: 3

Views: 927

Answers (2)

Vadim Hulevich
Vadim Hulevich

Reputation: 1833

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

Upvotes: 3

Jonas Wilms
Jonas Wilms

Reputation: 138537

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.

Upvotes: 5

Related Questions