Skip to main content

Command Palette

Search for a command to run...

JavaScript Promises — Explained Through Real-Life Stories You’ll Never Forget

A Simple Real-Life Analogy to Understand JavaScript Promises

Updated
8 min read
JavaScript Promises — Explained Through Real-Life Stories You’ll Never Forget

Most developers learn Promises.

Very few actually understand them.

If you’ve ever felt confused about Promise.all(), Promise.any(), or why race() behaves differently from allSettled(), this blog is going to change that. Not because we’ll throw complicated definitions at you — but because we’ll connect every method to something you’ve already experienced in real life.

By the end of this post, you won’t just remember the methods.

You’ll feel how they work.


What Is a Promise? — The Job Interview Callback Story 💼

Imagine you apply for a job.

You submit your resume. After a few days, the company sends you an email saying:

“We’ve received your application. We’ll get back to you soon.”

Now think about this carefully.

You don’t know the result yet.
You don’t know whether you got selected or rejected.
But you do know one thing:

You will receive an answer in the future.

That situation is exactly what a Promise is in JavaScript.


What’s Happening Behind the Scenes?

After sending that email, the company starts reviewing your resume.

HR is checking your qualifications.
The manager is reviewing your experience.
They are making a decision.

But while all of this is happening…

You don’t stop your life.

You continue learning.
You apply to other companies.
You go on with your daily routine.

Similarly, in JavaScript:

When you make an API request or start an asynchronous task, JavaScript doesn’t stop everything. It continues running other code while waiting for the result.

It simply says:

“I’ve started this task. When it’s finished, I’ll give you the result.”


The Three States of a Promise (Interview Version)

Pending — Application Under Review

Your resume has been submitted.

The company is reviewing it.

No decision yet.

You are waiting.

That is Pending.


Fulfilled — You Got the Job

You receive an email:

“Congratulations! You have been selected.”

That is Fulfilled — the promise succeeded.


Rejected — Application Not Selected

You receive another type of email:

“Thank you for applying, but we have decided to move forward with another candidate.”

That is Rejected — the promise failed.


Why Promises Become Powerful

Now imagine you applied to:

  • Company A

  • Company B

  • Company C

All of them are reviewing your applications at the same time.

Now different scenarios can happen:

  • You want responses from all companies before deciding → like Promise.all()

  • You want to see who rejected and who selected you → like Promise.allSettled()

  • You accept the first offer you receive → like Promise.race()

  • You just need at least one company to select you → like Promise.any()

And suddenly…

Promises don’t feel technical anymore.

They feel real.


The Real Magic: Static Promise Methods

When working with multiple asynchronous tasks, JavaScript gives us powerful static methods:

  • Promise.all()

  • Promise.allSettled()

  • Promise.race()

  • Promise.any()

  • Promise.resolve()

  • Promise.reject()

Each one handles multiple promises differently.

Instead of memorizing rules…

Let’s experience them.


1️⃣ Promise.all() — The Family Dinner Rule

Imagine you’re hosting a big family dinner. Everyone has promised to arrive by 8 PM, and there’s one simple rule: the dinner will begin only when every single person is seated at the table. If your cousin is stuck in traffic, everyone waits. If your uncle cancels at the last minute, the entire dinner plan collapses.

That’s exactly how Promise.all() behaves.

It waits for all promises to succeed. If even one fails, the entire operation fails immediately.

How It Works

  • Waits for all promises

  • Fails fast if one rejects

  • Returns results in the original order

Example

const pizza = Promise.resolve("🍕 Pizza ready");
const drinks = Promise.resolve("🥤 Drinks ready");
const dessert = Promise.resolve("🍰 Dessert ready");

Promise.all([pizza, drinks, dessert])
  .then(results => console.log(results))
  .catch(error => console.log(error));

If one fails:

const drinks = Promise.reject("Drinks spilled");

Promise.all([pizza, drinks, dessert])
  .then(results => console.log(results))
  .catch(error => console.log(error));

The whole thing rejects instantly.

When To Use It

Use Promise.all() when:

  • You need all results to proceed

  • One failure should stop everything

  • Example: Loading user profile + posts + notifications together


2️⃣ Promise.allSettled() — Exam Results Day

Imagine your semester exam results day. You had five subjects. Some went well, some didn’t. When the results are announced, you don’t stop checking after seeing one failed subject. You still want to know the outcome of every single paper — pass or fail.

That’s the spirit of Promise.allSettled().

It waits for all promises, regardless of whether they succeed or fail, and gives you a detailed report of each one.

How It Works

  • Waits for all promises

  • Never rejects

  • Returns status + value/reason for each

Example

const math = Promise.resolve("Math Passed");
const physics = Promise.reject("Physics Failed");
const chemistry = Promise.resolve("Chemistry Passed");

Promise.allSettled([math, physics, chemistry])
  .then(results => console.log(results));

Output structure:

[
  { status: "fulfilled", value: "Math Passed" },
  { status: "rejected", reason: "Physics Failed" },
  { status: "fulfilled", value: "Chemistry Passed" }
]

When To Use It

Use Promise.allSettled() when:

  • You want complete visibility

  • Failures shouldn’t stop the process

  • Example: Uploading multiple images and reporting which failed


3️⃣ Promise.race() — The 100-Meter Sprint

Imagine standing at the edge of a 100-meter race. The whistle blows, runners sprint forward, and you focus only on one thing — whoever crosses the finish line first. It doesn’t matter who comes second or third. The first result decides the outcome.

That’s exactly how Promise.race() behaves.

It resolves or rejects as soon as the first promise settles — whether it’s a success or failure.

How It Works

  • Returns the first settled promise

  • Could resolve or reject

  • Doesn’t wait for others

Example

const slowServer = new Promise(resolve =>
  setTimeout(() => resolve("Slow server responded"), 3000)
);

const fastServer = new Promise(resolve =>
  setTimeout(() => resolve("Fast server responded"), 1000)
);

Promise.race([slowServer, fastServer])
  .then(result => console.log(result));

The fast server wins.

When To Use It

Use Promise.race() when:

  • You want the fastest response

  • Implementing timeouts

  • Example: API request vs timeout fallback


4️⃣ Promise.any() — Finding Any Ride Home

It’s raining heavily, and you desperately need a ride home. You open Uber, Ola, and Rapido simultaneously. You don’t care which one accepts first — you just need one confirmation. If Uber rejects, fine. If Ola rejects, fine. As long as one says “Driver on the way,” you’re safe.

That’s Promise.any().

It returns the first successful promise and ignores failures. It only fails if all promises fail.

How It Works

  • Returns first fulfilled promise

  • Ignores rejections

  • Rejects only if all fail

Example

const uber = Promise.reject("Uber unavailable");
const ola = Promise.reject("Ola unavailable");
const rapido = Promise.resolve("Rapido accepted ride");

Promise.any([uber, ola, rapido])
  .then(result => console.log(result))
  .catch(error => console.log(error));

If all fail, it throws an AggregateError.

When To Use It

Use Promise.any() when:

  • You need at least one success

  • Multiple fallback sources exist

  • Example: Fetching data from multiple mirror servers


5️⃣ Promise.resolve() — Instant Approval

Sometimes you don’t need to wait at all. Imagine applying for a student discount and the shopkeeper instantly approves it without checking anything.

That’s Promise.resolve() — it creates an already-fulfilled promise.

Promise.resolve("Approved")
  .then(result => console.log(result));

Useful for:

  • Wrapping non-promise values

  • Testing promise chains


6️⃣ Promise.reject() — Instant Rejection

Now imagine applying for something and being rejected immediately — no waiting, no processing.

That’s Promise.reject().

Promise.reject("Access Denied")
  .catch(error => console.log(error));

Useful for:

  • Manually triggering errors

  • Testing error handling


Quick Comparison Table

Method Real-Life Analogy Waits For All? Fails Fast? Returns
all() Family dinner Yes Yes All results
allSettled() Exam results Yes No Status report
race() 100m sprint No First settles First result
any() Ride booking apps No Only if all fail First success

The Common Difference

  • all() → Everyone must succeed

  • allSettled() → Tell me what happened to everyone

  • race() → Whoever finishes first

  • any() → Just give me one success


Final Thoughts

Promises are not complicated.

They are simply different ways of handling the future.

Sometimes you need everyone.
Sometimes you need visibility.
Sometimes you need speed.
Sometimes you just need one win.

And once you connect these methods to real life…

You’ll never confuse them again.


If this helped you truly understand Promises, share it with someone who still thinks Promise.all() and Promise.any() are the same thing.

They’ll thank you later.