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:
- Iron Man upgrading his suit.
- Thor summoning lightning.
- Hulk meditating to control his anger.
Each mission will be represented as a promise.
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.
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:
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.
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:
Mission failed: Thor lost his hammer! π¨
Additional Cases for Promise.all()
β
Case 1: Multiple Rejections β
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:
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.
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:
First hero ready: Thor is ready β‘
Case 1: Fastest Rejection β
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:
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? β
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:
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 β
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:
Mission 1 succeeded: Iron Man is ready π¦Ύ
Mission 2 succeeded: Thor is ready β‘
Mission 3 succeeded: Hulk is ready πͺ
Case 2: All Promises Reject β
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:
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 usingPromise.all()
orPromise.race()
. - Assuming order of resolution: Promises may resolve in a different order than they appear in the array.
- Overusing
Promise.race()
: Remember thatPromise.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!