Demystifying Promise.all, Promise.race(), and Promise.allSettled in JavaScript

In this blog, we are going to learn about different utility methods that we have with promises and how sometimes these methods make our life easy but before going deep into that let us understand what even promise means. So in javascript to handle asynchronous operations we use promises and they allow us to execute the code that takes longer time to execute as we know javascript is a synchronous and single-threaded language but we perform many asynchronous operations such as making an API request or querying a database, without blocking the main thread of execution and this is where promises help us a lot.

In the real-world application, we won't be dealing with a single promise always there will be scenarios when we have multiple promises and these promise utility methods help us to perform common operations on these all promises let's learn all these promise utility methods.

  1. Promise. all(): This utility method of promise will take an array of promises as input and it will return us a new promise. Here we need to understand one thing the new promise will be resolved only when all the promises from the input array get resolved if any of them will be rejected then our output promise will also going to through an error. Let's understand it by example.

     const firstPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('Result from first promise');
       }, 200);
     });
    
     const secondPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('Result from second promise');
       }, 400);
     });
    
     const thirdPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('Result from third promise');
       }, 600);
     });
    
     Promise.all([firstPromise, secondPromise,thirdPromise])
       .then((results) => {
        // i will come here only if all promises are resolved
         console.log(results);
       })
       .catch((error) => {
        // If any promise fails i will come here.
         console.log(error);
       });
    
     // OUTPUT WILL BE 
     /*
        ["Result from second promise","Result from second promise",
         "Result from third promise"]
     */
    

    In the above code example, we can see that Promise.all() method is useful when we have multiple promises and we want to execute all of them together also here execution of promise will be done in parallel means as soon as you execute the above code all the promises will be triggered together and output will come only when all of them are resolved. Also, it will go to .then() when all the promises are successfully resolved but if in any case if single promise failed then it will go to .catch() and print the error message for the failed promise.

  2. Promise. race(): This utility method will also take an array of promises as input and will return a new promise and this new promise will be resolved or rejected as soon as the first promise from the input array gets resolved or rejected. Suppose in the input array we have 5 different promises now if you put all these promises into Promise.race() then from all these 5 promises if any one of them gets resolved or rejected then Promise. race() will also return that resolved or rejected promise and won't wait for the other 4 promises to get done with their job. Let's understand it by example.

     const firstPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('First will be lose the game');
       }, 600);
     });
    
     const secondPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('Second promise will win the game because 100 ms it will be resolved');
       }, 100);
     });
    
     const thirdPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('No chance in game because 10000 ms is to much');
       }, 10000);
     });
     Promise.race([firstPromise, secondPromise,thirdPromise])
       .then((result) => {
         console.log(result);
       })
       .catch((error) => {
         console.log(error);
       });
    
     // Output will be
     /*
     Second promise will win the game because 100 ms it will be resolved
     */
    

    In the above example, we have three promises and as we can see the first one will be resolved in 600ms the second one will be resolved in 100ms and the third one will be resolved in 10000ms and as we know with Promise. race() the promise that gets resolved or gets rejected first will be output and because of that, we are getting output "Second promise will win the game because 100 ms it will be resolved" as it gets resolved in 100ms.

  3. Promise. allSettled(): This utility method is directly connected with Promise. all() and the only major difference is how they handle rejected promises. In case of Promise.all() if any of the input promises reject, the returned promise immediately rejects and the rejection reason is passed to the catch block. This means that you need to handle errors using .catch() when using Promise.all(). With Promise. allSettled(), even if some of the input promises reject, the returned promise still resolves with an array of objects, one for each input promise. Each object in the array contains the outcome of the corresponding input promise, whether it was fulfilled or rejected, and the rejection reason is included in the object for rejected promises. Let's understand it by example.

     const firstPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         reject('First love always get rejected');
       }, 600);
     });
    
     const secondPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('Second time you will not make same mistake again');
       }, 100);
     });
    
     const thirdPromise = new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('Third time no chance to loss the game');
       }, 10000);
     });
    
     Promise.allSettled([firstPromise, secondPromise,thirdPromise])
       .then((result) => {
         console.log(result);
       })
    
     // Output will be
     [
       { status: 'rejected', reason: Error: First love always get rejected' },
       { status: 'fulfilled', value: 'Second time you will not make same mistake again' },
       { status: 'fulfilled', value: 'result : 'Third time no chance to loss the game' }
     ]
    
     // See in array output how it gives info about rejected promises also so no more need on .catch method here.
    

    In conclusion, Promise utility methods like Promise.all(), Promise. race(), and Promise.allSettled() are powerful tools for working with asynchronous JavaScript code we just need to understand when to use which utility method. And that's all from this blog and thanks for reading hope you enjoyed it :).