Before we dive into our midnight adventure, let's quickly understand what Promises are in JavaScript. Don't worry - it's easier than facing a monster under the bed!
What is a Promise?
A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation. Think of it like a real-life promise: your friend promises to bring you coffee. Right now, you don't have the coffee - the promise is pending. Later, either you get the coffee (fulfilled) or your friend calls to say they spilled it (rejected).
In JavaScript, a Promise is created using the new Promise() constructor, which takes a function with two parameters: resolve and reject. You call resolve(value) when the operation succeeds, and reject(error) when it fails.
const coffeePromise = new Promise((resolve, reject) => {
// Simulate making coffee
const success = true;
if (success) {
resolve("β Here's your coffee!");
} else {
reject("π Spilled the coffee...");
}
});
Then and Catch
Once you have a Promise, you can attach .then() and .catch() methods to handle the result.
-
.then()runs when the Promise is fulfilled (resolved). It receives the resolved value. -
.catch()runs when the Promise is rejected. It receives the error.
coffeePromise
.then((message) => {
console.log(message); // "β Here's your coffee!"
})
.catch((error) => {
console.log(error); // "π Spilled the coffee..."
});
You can also chain multiple .then() calls, but we'll keep it simple for now.
Now that you know the basics, let's see how Promises can help you survive a terrifying 3:34 AM bathroom trip - with a little help from Promise.all, Promise.allSettled, Promise.race, and Promise.any.
It's 3:34 AM.
You wake up suddenly, and your bladder is screaming at you like a DDOS attack. You need to go to the bathroom. But there is a problem.
You are living alone in the house and have heard the stories from your grandmother that after 3 AM Ghosts lurk around the house. The monsters under the bed are most active. And your Hallway becomes a road to hell.
You lie frozen and starts to think about your options. Either wet the bed or face the darkness (Supernatural being).
This, my friends, is exactly like handling multiple promises in JavaScript.
Let me explain -
Before you get out of the bed you need three things to happen:
- You flip the switch of the hallway and hope it works.
- You flip the bathroom light and hope it works.
- You check under the bed and hope there is no Monster looking back at you while salivating πΉ.
Lets code the Conditions :
Condition 1
const hallwayLight = new Promise((resolve, reject) => {
// You flip the switch (You are an developer bruh! You can do anything from bed)
const bulbWorks = Math.random() > 0.3; // 70% chance it works
setTimeout(() => {
if (bulbWorks) {
resolve("π‘ Hallway light is ON");
} else {
reject("π Hallway light bulb is dead");
}
}, 1000);
});
Condition 2
const bathroomLight = new Promise((resolve, reject) => {
// You flip the bathroom switch from bed (You have a Smart bulb!!!)
const bulbWorks = Math.random() > 0.2; // 80% chance it works
setTimeout(() => {
if (bulbWorks) {
resolve("π½ Bathroom light is ON");
} else {
reject("π» Bathroom light is dead");
}
}, 1500);
});
Condition 3
const underBedCheck = new Promise((resolve, reject) => {
// You shine your phone flashlight under the bed
const monsterPresent = Math.random() > 0.6; // 40% chance of monster
setTimeout(() => {
if (!monsterPresent) {
resolve("ποΈ Under the bed is CLEAR");
} else {
reject("πΉ MONSTER under the bed!");
}
}, 2000);
});
Now, depending on your personality type (and your level of desperation), you'll handle these promises differently.
1. Promise.all()
You ask yourself: "I will ONLY get out of bed if ALL THREE things happen. The hallway light MUST turn on. The bathroom light MUST turn on. And there MUST be no monster under the bed. If ANY of these fail, I'm staying right here."
Is the hallway light bulb dead? Well, I'm peeing in bed tonight.
The bathroom light works. No monster under the bed. But who cares? The hallway light failed. The contract is broken. The deal is off. You lie there, defeated, as warm surrender spreads beneath you.
Situation:
Promise.all([hallwayLight, bathroomLight, underBedCheck])
.then((results) => {
console.log("π All systems go! Time to sprint!");
console.log(results);
// You get out of bed and run with tears of happiness
})
.catch((error) => {
console.log("π NOPE. Staying in bed.");
console.log("Reason:", error);
// You wet the bed. Game over.
});
Outcome:
On success -
π All systems go! Time to sprint!
['π‘ Hallway light is ON', 'π½ Bathroom light is ON', 'ποΈ Under the bed is CLEAR']
On Failure -
π NOPE. Staying in bed.
Reason: π Hallway light bulb is dead
When to use Promise.all()
- When you need all API calls to succeed before rendering a page.
- When you're uploading multiple files and need all to complete.
2. Promise.allSettled()
You are more practical. You decide: "Let me check EVERYTHING first. I'll wait until I know the status of all three safety measures. Then I'll make a decision based on reality."
You check:
- Hallway light? Dead. (Rejected)
- Bathroom light? Works! (Fulfilled)
- Under the bed? Clear! (Fulfilled)
Okay, so you have partial information. The hallway is dark, but you have your phone. You can see the bathroom light at the end. No monsters. You make a run for it, using your phone as a flashlight.
Situation:
Promise.allSettled([hallwayLight, bathroomLight, underBedCheck])
.then((results) => {
console.log("π Let's assess the situation:");
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`β
Promise ${index + 1}:`, result.value);
} else {
console.log(`β Promise ${index + 1}:`, result.reason);
}
});
const anyLight = results.some(r =>
r.status === 'fulfilled' &&
(r.value.includes('light') || r.value.includes('CLEAR'))
);
if (anyLight) {
console.log("π Good enough! Making a run for it!");
} else {
console.log("π± Complete darkness AND monsters? Staying put.");
}
});
Outcome
π Let's assess the situation:
β Promise 1: π Hallway light bulb is dead
β
Promise 2: π½ Bathroom light is ON
β
Promise 3: ποΈ Under the bed is CLEAR
π Good enough! Making a run for it!
When to use Promise.allSettled()
- When you need to know the outcome of all operations regardless of failures.
- When uploading multiple files and you want to know which succeeded/failed.
- When you're running a batch process and need a complete report.
3. Promise.race()
Your bladder is at critical mass. You can't wait for all checks. You can't even wait for the first successful check. You just need the FIRST thing to happen, ANYTHING, so you can react.
You swing your legs out of bed. That's the first action. You're committed now. You hear a creak? Too bad. You're running. The first event triggered your sprint, and there's no stopping.
This is reckless. This is how horror movies start. But you gotta go.
Situation
Promise.race([hallwayLight, bathroomLight, underBedCheck])
.then((firstResult) => {
console.log(`π First thing happened: ${firstResult}`);
console.log("π Taking that as a sign! Running NOW!");
// You sprint regardless of what the first result was
})
.catch((firstError) => {
console.log(`π First thing happened (and it was bad): ${firstError}`);
console.log("π° Oh no. That's a bad sign. But I'm already out of bed!");
// You're already committed. You run into darkness.
});
Outcome
On success -
π First thing happened: π‘ Hallway light is ON
π Taking that as a sign! Running NOW!
On failure -
π First thing happened (and it was bad): πΉ MONSTER under the bed!
π° Oh no. That's a bad sign. But I'm already out of bed!
*Screaming intensifies*
When to use Promise.race()
- When implementing timeouts (
Promise.race([actualRequest, timeoutPromise])). - When you need the fastest response from multiple sources.
4. Promise.any()
You're smart. You need one successful safety measure. Just one. You try the hallway light:
Click. Nothing. Darkness. (Rejection)
Okay, scary, but you're not giving up. You try the bathroom light:
Click. LIGHT! (Fulfilled)
YES! You can see the bathroom door! You don't care about the monster under the bed anymore. You have light. You run.
If ALL three fail? No lights, monster under bed? Then you're truly doomed. You stay in bed and accept your fate.
Situation:
Promise.any([hallwayLight, bathroomLight, underBedCheck])
.then((firstSuccess) => {
console.log(`π― Found one working safety measure: ${firstSuccess}`);
console.log("π That's enough! Making my move!");
})
.catch((error) => {
console.log("π ALL safety measures failed!");
console.log("Errors:", error.errors); // AggregateError
console.log("Staying in bed forever.");
});
Outcome
On Success -
π― Found one working safety measure: π½ Bathroom light is ON
π That's enough! Making my move!
On failure -
π ALL safety measures failed!
Errors: ['π Hallway light bulb is dead', 'π» Bathroom light is dead', 'πΉ MONSTER under the bed!']
Staying in bed forever.
When to use Promise.any()
- When you need any successful response from multiple sources.
- When implementing fallback APIs (try server A, if it fails, try server B).
The Moral of the Story
- If you're a control freak, use
Promise.all()and accept that you'll sometimes wet the bed. - If you're a data analyst, use
Promise.allSettled()and make informed decisions. - If you're desperate, use
Promise.race()and hope for the best (but probably scream a lot). - If you're smart, use
Promise.any()and take the first win you can get.
And remember: Always check for monsters before getting out of bed at 3 AM. Or use Promise.any() and just need one light to work.
πΉοΈ Play the Game
If you enjoyed this story, you'll love the pixel-art game I built to go with it. Click the screenshot below, choose your Promise method, and survive the night!
Hope you liked this Story. If there's any mistake or something I can improve, do tell me. You can find me on LinkedIn and X, I post more stuff there.








Top comments (2)
I liked the read, the game at the is awesome too
No way bro even cooked up a game