Skip to main content

Command Palette

Search for a command to run...

The Promise That Taught Me Patience ☕

A Developer Story About JavaScript Promise Methods

Updated
4 min read
The Promise That Taught Me Patience ☕

I still remember the day I truly understood Promises.

It was 2:17 AM.
My coffee was cold.
My API wasn’t responding.
And my console was full of errors.

I was building a simple dashboard. Just fetch user data. Display it. Easy.

Except it wasn’t.

That night, I didn’t just learn Promises.
I learned the methods of Promises and they changed how I think about async JavaScript forever. Let me tell you the story.


Chapter 1: The First Promise (And the First Mistake)

I wrote this:

fetch("/api/user")
  .then(response => response.json())
  .then(data => console.log(data));

It worked.

I felt powerful.

Until the server crashed.

Suddenly… nothing worked.

That’s when I met my first real Promise method.


.catch() — The Safety Net

I learned that async code without error handling is like riding a bike without brakes.

So, I added:

fetch("/api/user")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("Something broke:", error));

And boom.

Now when the server failed, my app didn’t die silently.

What .catch() Really Does

  • It handles rejected promises.

  • It catches errors from any previous .then() in the chain.

  • It keeps your app from crashing unexpectedly.

That night, .catch() felt like a superhero.


Chapter 2: The Cleanup Nobody Talks About

I added a loading spinner.

But when the request failed… the spinner kept spinning. Forever.

Users thought my app was haunted.

That’s when I discovered:


.finally() — The Cleaner

fetch("/api/user")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => {
    hideSpinner();
  });

Now the spinner disappeared whether the request succeeded or failed.

What .finally() Does

  • Runs after the Promise settles.

  • Doesn’t care if it was fulfilled or rejected.

  • Perfect for cleanup logic (spinners, closing DB connections, etc.)

It’s the responsible adult of Promise methods.


Chapter 3: When One API Wasn’t Enough

Then my manager said:

“We also need user posts. And notifications. And activity logs.”

Three APIs.

All needed together.

Welcome to Promise teamwork.


Promise.all() — The Team Player

Promise.all([
  fetch("/api/user"),
  fetch("/api/posts"),
  fetch("/api/notifications")
])
  .then(responses => Promise.all(responses.map(r => r.json())))
  .then(data => {
    console.log("All data:", data);
  })
  .catch(error => console.error("One of them failed:", error));

What Promise.all() Does

  • Runs multiple promises in parallel.

  • Waits for all to succeed.

  • Fails immediately if one fails.

It’s strict.

If one teammate fails, the whole team fails.

But when everything works? It’s blazing fast.


Chapter 4: The Real World Is Messy

But here’s the problem.

Sometimes one API fails.

But I still wanted partial data.

That’s when I met the forgiving sibling.


Promise.allSettled() — The Diplomat

Promise.allSettled([
  fetch("/api/user"),
  fetch("/api/posts"),
  fetch("/api/notifications")
])
  .then(results => {
    console.log(results);
  });

Now I got results like:

[
  { status: "fulfilled", value: ... },
  { status: "rejected", reason: ... },
  { status: "fulfilled", value: ... }
]

What Promise.allSettled() Does

  • Waits for all promises.

  • Never fails early.

  • Returns the result of each promise individually.

Perfect for dashboards.

Perfect for real apps.

Perfect for imperfect APIs.


Chapter 5: The Race Condition

Then came performance optimization.

I had two mirror servers.

I wanted the fastest response.

Enter:


Promise.race() — The Sprinter

Promise.race([
  fetch("https://server1.com/data"),
  fetch("https://server2.com/data")
])
  .then(response => console.log("Fastest response received"))
  .catch(error => console.error(error));

What Promise.race() Does

  • Returns the first promise that settles.

  • Doesn’t care if it’s success or failure.

  • Speed over certainty.

It’s fast.
It’s risky.
It’s powerful.


Chapter 6: The First Success Wins

Then I found a better alternative for fallback APIs.

What if:

  • Try multiple servers

  • Ignore failures

  • Return the first successful response

That’s when I discovered:


Promise.any() — The Optimist

Promise.any([
  fetch("https://server1.com/data"),
  fetch("https://server2.com/data"),
  fetch("https://backup.com/data")
])
  .then(response => console.log("First successful response"))
  .catch(error => console.error("All failed:", error));

What Promise.any() Does

  • Returns the first fulfilled promise.

  • Ignores rejected ones.

  • Throws error only if all fail.

It’s the “never give up” method.

The Big Realization

That 2:17 AM debugging session taught me something deeper.

Promises aren’t just syntax.

They represent real-life developer situations:

The Moral of the Story

JavaScript Promises are not about async code.

They’re about:

  • Handling uncertainty

  • Managing expectations

  • Recovering from failure

  • Writing resilient systems

If you’re a developer reading this at 2 AM with coffee…

Add .catch().

Add .finally().

And trust the Promise.