Introduction
Hello my fellow coders and curious minds!
If you've ever dived into asynchronous JavaScript, you know Promises are like that reliable friend who handles the chaos of waiting for that group trip.
But let's make this super duper relatable – we'll draw parallels from everyday Indian life, like arranged marriages, family dramas, job hunts, and even those intense cricket matches. By the end, you'll not only grasp the basics but also master methods like .all(), .allSettled(), .race(), and .any(). We'll sprinkle in code snippets to see them in action.
Before we jump into the methods, let's build the foundation. Think of Promises as the backbone of handling async operations without blocking your code – like not pausing your life in a hell while waiting for the response to a marriage proposal🙂
The Basics of Promises: Like Proposing in an Arranged Marriage Setup
In Indian society, arranged marriages are common, right?! You meet someone through family, and there's this nerve-wracking wait for their response. That's exactly what a Promise represents: a future value that might succeed or fail.
If we see the technical definition, it says: The Promise object represents the eventual completion or failure of an asynchronous operation and its resulting value. I know, at first it might feel confusing but I assure you after reading this blog completely, you will be like master in Promises.
The Three States of a Promise
A Promise can be in one of three states:
- Pending: The initial or default state, like when you've proposed but haven't heard back yet. Everything's up in the air – will it be a yes or no?😕
- Fulfilled (Resolved): Success! They've said yes, and you're moving forward with wedding plans.🎉
- Rejected: Ouch, a no. Maybe I should not talk about this further.🤧
Just like this real life sccenario, once a Promise settles down(fulfilled or rejected), it doesn't change state further. No take-backs!!
The Promise Constructor: The Proposer's Dilemma
To create a Promise, you use the Promise constructor, which takes a resolver function as a parameter. This resolver runs immediately and gets two arguments: resolve(fulfill/success) and reject(failure). These are like the tools the proposer uses to see the outcome.
- resolve(value): Call this when things go well, passing the successful result (e.g., "Yes, let's get married!").
- reject(error): Call this if it fails, passing the reason (e.g., "Sorry, not interested💔").
Promises shine when dealing with asynchronous operations, like waiting for a response that takes time for example: DB call, cryptography etc. Think of it as the family taking a few days to discuss the proposal. In JavaScript, functions like setTimeout simulate such delays, allowing code to run after a specified time (in milliseconds). This is perfect for mimicking real-world waits, where the resolver doesn't resolve or reject instantly but after some async task completes.
Here's a simple code snippet simulating a proposal with a delay using setTimeout:
const marriageProposal = new Promise((resolve, reject) => {
setTimeout(() => {
// Simulate a 2-second family discussion
const familyApproval = Math.random() > 0.5; // Random chance, like our real life!
if (familyApproval) {
resolve("Yes! Let's plan the wedding.");
} else {
reject("No, family doesn't approve.");
}
}, 2000); // 2000ms = 2 seconds delay
});
console.log(marriageProposal); // Initially: Promise { <pending> }
// Runs first as it's not an asynchronous operation
setTimeout(() => {
console.log(marriageProposal); // After 2 seconds: Promise { <resolved> } or { <rejected> }
}, 2500);
In this analogy, the resolver is the family discussion starting right away, but the decision (resolve or reject) happens after a timeout – just like waiting for elders to mull over biodata and horoscopes. setTimeout doesn't block the code; it schedules the callback to run later, allowing other tasks to proceed meanwhile. This highlights how Promises manage async flow without freezing your app, unlike synchronous code.
I suggest you run the code by yourself, and if you run the code, then you can see an interesting output. If the problem gets resolved, then you will see the pending promise first, and then the resolved promise. Right? But for the rejected case, you will see there's showing an error after the pending state, and after that, it shows that the promise has got rejected. What actually happens is when the resolve or the reject function is called, then internally it returns the value which is passed within that resolve or reject function automatically i.e., for the resolved state, it won't print anything or it won't do anything as it is not handled later, and for the reject function, it marks the ppromise as rejected. Rejecting a Promise does not immediately throw a synchronous error. It simply marks the Promise as rejected. If no handler is attached, the runtime may later report it as an unhandled rejection.
So, for the promise cases, the handler is one of the most important things, so let's discuss the handling of promises.
Handling Promises: .then() and .catch()
Once the Promise is created, you handle its outcome with chaining methods. .then() is for the fulfilled state, and .catch() for the rejection – like having a backup plan if the proposal flops.
- .then(onFulfilled, onRejected): Handles success first, optionally rejection too. The actual syntax of .then can handle both the resolve state and the reject state, but to make the code cleaner and more readable, there is also another handler used, known as .catch.
- .catch(onRejected): Specifically for errors, it handles errors thrown inside .then() as well. It's like consoling yourself with chai after a rejection🫂.
Extending our code (note how it handles the async delay seamlessly):
marriageProposal
.then((response) => {
console.log("Great news:", response); // Logs after 2 seconds: "Yes! Let's plan the wedding."
return "Book the venue!"; // Chaining another step after the first one is successful (return value will be passed to the next .then())
})
.then((nextStep) => console.log(nextStep)) // If chained: "Book the venue!"
.catch((error) => console.error("Heartbreak:", error)); // After 2 seconds if rejected: "No, family doesn't approve."
Think of .then() chaining as the wedding progression: proposal success (after the wait) leads to venue booking, but a rejection skips straight to handling the fallout. Though both the resolve and reject state can have .then() chaining as per needed. This keeps your code clean and avoids callback hell – no nested functions like endless family calls! The async nature with setTimeout shows Promises' true power: your code continues running while waiting, just like life doesn't stop during those anxious proposal days.
Diving into Promise Methods: Like Navigating Family and Love in Desi Style
Alright, we've got the basics down – now let's level up to the powerhouse static methods of Promises: .all(), .allSettled(), .race(), and .any(). These are your go-to tools for managing multiple Promises at once, turning async chaos into controlled narratives. Imagine them as strategies in an Indian wedding or job hunt drama: sometimes you need everyone on board, other times just the fastest or the first positive vibe. We'll explore each with relatable analogies, code, and visuals to make it stick!
Promise.all(): The Family Approval Gauntlet
Now, onto the methods! Promise.all() takes an array of Promises and waits for all to fulfill. If even one rejects, the whole thing rejects – like needing unanimous family approval for a love marriage in Indian society. One disapproving auntie, and the whole plan crumbles!🤬
Analogy: Imagine proposing, but you need nods from parents, siblings, and grandparents. All must say yes; one no, and it's off.
Code snippet:
const parentApproval = Promise.resolve("Parents say yes!");
const siblingApproval = Promise.resolve("Siblings are thrilled!");
const grandparentApproval = Promise.reject("Grandparents disapprove – too modern!🙂");
Promise.all([parentApproval, siblingApproval, grandparentApproval])
.then(approvals => console.log("Marriage on!", approvals)) // Won't run
.catch(error => console.error("Plan cancelled:", error)); // "Grandparents disapprove..."
Output: Rejects with the first error. Use this for tasks where everything must succeed, like loading multiple resources for a web page.
Promise.allSettled(): The Job Interview Marathon
Unlike .all(), Promise.allSettled() waits for all Promises to settle (fulfill or reject) and returns an array of their outcomes – no short-circuiting. It's like applying to multiple jobs during campus placements: You want results from every interview, pass or fail, to learn and move on.
Analogy: You're interviewing at TCS, Infosys, and Wipro. Some offers come, some rejections, but you get the full report card to decide your next step📃
Code snippet:
const tcsInterview = Promise.resolve({ status: "fulfilled", value: "Offer received!✅" });
const infosysInterview = Promise.reject({ status: "rejected", reason: "Technical round failed❌" });
const wiproInterview = Promise.resolve({ status: "fulfilled", value: "Offer received!✅" });
Promise.allSettled([tcsInterview, infosysInterview, wiproInterview])
.then(results => {
console.log(results); // Array of objects: [{status: 'fulfilled', value: ...}, {status: 'rejected', reason: ...}, ...]
});
This is perfect for logging or batch operations where partial failures are okay.
Promise.race(): The Matrimonial Site Speed Date
Promise.race() settles as soon as the first Promise in the array does – win or lose. It's like speed dating on a matrimonial site: The first response (yes or no) decides if you pursue or move on, ignoring the rest.
Analogy: You're chatting with multiple matches on Shaadi.com. The quickest reply sets the tone – a fast yes means date night; a fast no means swipe
next.🏃
Code snippet:
const match1 = new Promise(resolve => setTimeout(resolve, 1000, "Yes, let's meet!"));
const match2 = new Promise((_, reject) => setTimeout(reject, 500, "Not interested."));
Promise.race([match1, match2])
.then(response => console.log("Quick win:", response)) // Won't run
.catch(error => console.error("Quick rejection:", error)); // "Not interested." (faster)
Great for timeouts or fastest API responses.
Promise.any(): The Optimistic Love Quest
Finally, Promise.any() waits for the first fulfillment, ignoring rejections until all fail (then it rejects with an AggregateError). It's optimistic, like pursuing love in Bollywood style: Keep trying matches until one clicks, brushing off nos.
Analogy: In a love life saga, you confess to crushes one by one. The first yes sparks romance; only if all reject do you feel the full heartbreak.
Code snippet:
const crush1 = Promise.reject("Friendzoned!😑");
const crush2 = Promise.reject("Already committed.😓");
const crush3 = Promise.resolve("Yes, let's date!😃");
Promise.any([crush1, crush2, crush3])
.then(response => console.log("Love found:", response)) // "Yes, let's date!😃"
.catch(error => console.error("All heartbreaks:", error.errors)); // Array of errors if all reject
Ideal for fallback APIs or any "first success" scenario.
Wrapping It Up: Promises – Your Reliable Companion in Code and Life
As we conclude this dive into JavaScript Promises, envision them as a loyal ally in Indian family tales, managing async uncertainties like waiting for the perfect rishta. We've covered the basics—states, constructors, and handling with .then() and .catch()—plus methods like .all() for consensus, .allSettled() for full reports, .race() for quick wins, and .any() for first successes.
These equip you for real async tasks, blending code with relatable analogies. Remember, Promises teach patience and structure. Experiment, connect personally, and code on—may your Promises always resolve happily! 🚀





Top comments (4)
Ritam, this article deserves a standing ovation! 👏 The 'Pending Proposals to Bollywood Bliss' title itself is a masterpiece. Quick question - how would you explain Promise.all() and Promise.race() with a desi analogy? Maybe a family wedding where everyone needs to arrive (all) vs who reaches first (race)? Would love to hear your take!
Thanks a ton man—they mean the world!
On your question, let's stick to the shaadi vibes.
For Promise.all(): Picture the groom arriving at the venue, and getting blocked by the bride's friends demanding for nek (that fun money ritual). He needs all his buddies to get in and negotiate—everyone's support is crucial for him, or the wedding stalls.
For Promise.race(): Think of those roaming snack trays at the reception, with the hottest chaat vanishing seconds after every refill. You need to race through the crowd to grab it first—whoever grabs it wins, ignoring the slower ones.
Hope that clicks! What's your favorite desi analogy for Promises? 😊
Haha this is gold, Ritam! 🔥
The Promise.all() with 'neg for all friends' is absolutely perfect! 😂 And Promise.race() as the chaat tray race - now I finally understand why I sprint at weddings! 🏃♂️
Here's my favorite analogy for you:
Promise.allSettled() is like family at a wedding - some arrive on time (fulfilled), some are late (pending), some leave early (rejected) - but at the end of the day, you still have to check on everyone and see how they're doing! 😄
You should turn this into a whole 'Desi Guide to Async Magic' series. This is exactly how India learns to code! What do you think?
Haha bhai, you're killing it! 😂
Brilliant man!
Family at a big fat Indian wedding — kuch log time pe aaye (fulfilled), kuch late pahunche (still pending), kuch khana khaake chupke se bhaag gaye (rejected) — par end mein sabko milke check karna hota hain ki “sab theek hai na?”
Exactly how .allSettled() works! I’m stealing this one for sure 😄
And yes, the series idea is ON!🔥
I’ve already started planning “Desi Guide to Async Magic” Part 2 (Async/Await + more detailed + more shaadi vibes).