Skip to content

Mastering JavaScript Promises β€” Superhero Edition πŸ¦Έβ€β™‚οΈπŸ¦Έβ€β™€οΈ ​

Welcome, aspiring JavaScript hero! Today, we'll embark on an exciting journey through JavaScript Promises, using superhero adventures to make learning fun. We'll explore how to handle multiple promises using Promise.all(), Promise.race(), and Promise.allSettled(). Get ready to team up with your favorite heroes and master asynchronous programming!

Introduction to Handling Multiple Promises ​

Imagine you're assembling a team of superheroes, each with their mission. Some missions depend on each other, while others can happen simultaneously. This is similar to handling multiple promises in JavaScript.

Key Point

When dealing with multiple asynchronous tasks that are independent, we can execute them concurrently for efficiency.

Understanding Promises ​

  • A Promise represents the eventual completion (or failure) of an asynchronous operation.
  • Promises can be in one of three states: pending, fulfilled, or rejected.

Handling Multiple Independent Promises ​

When multiple promises are independent, we can execute them concurrently.

The Superhero Missions ​

Let's consider three independent superhero missions:

  1. Iron Man upgrading his suit.
  2. Thor summoning lightning.
  3. Hulk meditating to control his anger.

Each mission will be represented as a promise.

javascript
let ironManMission = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Iron Man is ready 🦾");
  }, 2000);
});

let thorMission = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Thor is ready ⚑");
  }, 1000);
});

let hulkMission = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Hulk is ready πŸ’ͺ");
  }, 3000);
});

Using Promise.all() ​

Promise.all() takes an array of promises and returns a new promise that:

  • Resolves when all promises in the array have resolved.
  • Rejects if any promise in the array rejects.
javascript
Promise.all([ironManMission, thorMission, hulkMission])
  .then((results) => {
    console.log("All heroes are ready:");
    console.log(results);
  })
  .catch((error) => {
    console.log("Mission failed:", error);
  });

What will be the output, and when will it be logged? ​

Answer
  • Thor's mission resolves after 1 second.
  • Iron Man's mission resolves after 2 seconds.
  • Hulk's mission resolves after 3 seconds.
  • Since Promise.all() waits for all promises to resolve, the .then() block will execute after 3 seconds.

Output:

javascript
All heroes are ready:
["Iron Man is ready 🦾", "Thor is ready ⚑", "Hulk is ready πŸ’ͺ"]

What Happens If a Promise Rejects? ​

Suppose Thor encounters an issue and his mission rejects.

javascript
let thorMission = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Thor lost his hammer! πŸ”¨");
  }, 1000);
});

Promise.all([ironManMission, thorMission, hulkMission])
  .then((results) => {
    console.log("All heroes are ready:");
    console.log(results);
  })
  .catch((error) => {
    console.log("Mission failed:", error);
  });

What will happen in this case? Will the .then() block execute? ​

Answer
  • Thor's mission rejects after 1 second, causing Promise.all() to immediately reject.
  • The .catch() block will execute with the rejection reason, and the .then() block will not execute.

Output:

javascript
Mission failed: Thor lost his hammer! πŸ”¨

Additional Cases for Promise.all() ​

Case 1: Multiple Rejections ​

javascript
let ironManMission = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Iron Man's suit malfunctioned! πŸ’₯");
  }, 2000);
});

let thorMission = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Thor lost his hammer! πŸ”¨");
  }, 1000);
});

Promise.all([ironManMission, thorMission, hulkMission])
  .then((results) => {
    console.log("All heroes are ready:");
    console.log(results);
  })
  .catch((error) => {
    console.log("Mission failed:", error);
  });

Which error will be caught, and when? ​

Answer
  • Thor's mission rejects after 1 second.
  • Iron Man's mission rejects after 2 seconds.
  • Promise.all() rejects immediately when the first promise rejects, so Thor's mission rejection will be caught.

Output:

javascript
Mission failed: Thor lost his hammer! πŸ”¨

Using Promise.race() ​

Promise.race() returns a promise that:

  • Settles (resolves or rejects) as soon as any of the promises in the array settles.
javascript
Promise.race([ironManMission, thorMission, hulkMission])
  .then((result) => {
    console.log("First hero ready:", result);
  })
  .catch((error) => {
    console.log("Mission failed:", error);
  });

Which result will be logged first? ​

Answer
  • Thor's mission resolves in 1 second, so it will be the first result.

Output:

javascript
First hero ready: Thor is ready ⚑

Case 1: Fastest Rejection ​

javascript
let ironManMission = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Iron Man's suit malfunctioned! πŸ’₯");
  }, 500); // Rejects in 0.5 seconds
});

Promise.race([ironManMission, thorMission, hulkMission])
  .then((result) => {
    console.log("First hero ready:", result);
  })
  .catch((error) => {
    console.log("Mission failed:", error);
  });

What will be the output now? ​

Answer
  • Iron Man's mission rejects in 0.5 seconds.
  • Promise.race() settles with the first settled promise, which rejects in this case.

Output:

javascript
Mission failed: Iron Man's suit malfunctioned! πŸ’₯

Using Promise.allSettled() ​

Promise.allSettled() returns a promise that:

  • Resolves after all the promises have settled (either fulfilled or rejected).
  • Provides an array of objects describing the outcome of each promise.

How can we use Promise.allSettled() to get the status of all hero missions? ​

javascript
Promise.allSettled([ironManMission, thorMission, hulkMission]).then(
  (results) => {
    results.forEach((result, index) => {
      if (result.status === "fulfilled") {
        console.log(`Mission ${index + 1} succeeded: ${result.value}`);
      } else {
        console.log(`Mission ${index + 1} failed: ${result.reason}`);
      }
    });
  }
);

Suppose Iron Man's mission fails as before. ​

Answer

Output:

javascript
Mission 1 failed: Iron Man's suit malfunctioned! πŸ’₯
Mission 2 succeeded: Thor is ready ⚑
Mission 3 succeeded: Hulk is ready πŸ’ͺ

Additional Cases for Promise.allSettled() ​

Case 1: All Promises Fulfill ​

javascript
let ironManMission = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Iron Man is ready 🦾");
  }, 2000);
});

let thorMission = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Thor is ready ⚑");
  }, 1000);
});

let hulkMission = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Hulk is ready πŸ’ͺ");
  }, 3000);
});

Promise.allSettled([ironManMission, thorMission, hulkMission]).then(
  (results) => {
    results.forEach((result, index) => {
      console.log(`Mission ${index + 1} succeeded: ${result.value}`);
    });
  }
);

What will be the output? ​

Answer

Output:

javascript
Mission 1 succeeded: Iron Man is ready 🦾
Mission 2 succeeded: Thor is ready ⚑
Mission 3 succeeded: Hulk is ready πŸ’ͺ

Case 2: All Promises Reject ​

javascript
let ironManMission = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Iron Man's suit malfunctioned! πŸ’₯");
  }, 1000);
});

let thorMission = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Thor lost his hammer! πŸ”¨");
  }, 2000);
});

let hulkMission = new Promise((resolve, reject) => {
  setTimeout(
    () => {
      reject("Hulk couldn't control his anger! 😠");
    },

    1500
  );
});

Promise.allSettled([ironManMission, thorMission, hulkMission]).then(
  (results) => {
    results.forEach((result, index) => {
      console.log(`Mission ${index + 1} failed: ${result.reason}`);
    });
  }
);

What will be the output? ​

Answer

Output:

javascript
Mission 1 failed: Iron Man's suit malfunctioned! πŸ’₯
Mission 2 failed: Thor lost his hammer! πŸ”¨
Mission 3 failed: Hulk couldn't control his anger! 😠

Happy coding, and may your JavaScript journey be as adventurous as any superhero mission! πŸš€


This version uses VitePress ::: details blocks for folding and includes ASCII timelines to better illustrate the time-based flow of promises.

Summary

  • Promise.all() rejects immediately if any promise rejects.
  • Promise.race() settles as soon as any promise settles.
  • Promise.allSettled() waits for all promises to settle, regardless of their outcome.

Common Pitfalls

  • Forgetting to handle rejections: Always include .catch() when using Promise.all() or Promise.race().
  • Assuming order of resolution: Promises may resolve in a different order than they appear in the array.
  • Overusing Promise.race(): Remember that Promise.race() settles on the first promise, which might be a rejection.

Conclusion ​

Congratulations on mastering how to handle multiple promises in JavaScript! By using Promise.all(), Promise.race(), and Promise.allSettled(), you can effectively manage asynchronous operations, just like coordinating a team of superheroes on a mission.


Keep practicing and applying these concepts to your projects, and soon you'll be a master of JavaScript promises!

Additional Resources ​