Skip to main content

Command Palette

Search for a command to run...

Promise Utility & Concurrency Methods: A Goa Trip Story

What Planning a Goa Trip Taught Me About Promise Concurrency

Updated
7 min read
Promise Utility & Concurrency Methods: A Goa Trip Story
S
Full-stack developer obsessed with performance, scalability, and clean systems. I use Arch btw.

Introduction: A Trip to Goa

Imagine you're at that classic point in your life, where you try to plan a trip to Goa with your friends. We all know the ultimate output of such plans, don't we? 👀 However, we still try with the dream of finally having a trip like "Zindagi Na Milegi Dobara".

So imagine you're the guy who's reaching out to everyone in your group, trying to finalize a trip to Goa. Let's explore various Promise Utility and Concurrency Methods in JavaScript from this lens 🧐, and trust me, you'll never forget them!

Think of Promises like waiting for your friends to confirm a trip. Each friend’s reply is uncertain. The different Promise methods simply define how strict you want to be about who joins the trip.

Promise States: Your Friends' Replies

Before we deep dive into Promise Utility and Concurrency Methods, let's take a quick look at the different states a promise can be in. These states are like the replies your friends can give you in our analogy. There are primarily 3 states:

✅ Fulfilled

The fulfilled state denotes successful completion of a Promise. It's like your friend saying "yes" to go on the trip with you (sounds dreamy, right? 😵‍💫).

❌ Rejected

The rejected state denotes failure in fulfilling a Promise. Thus, you must have guessed it, it's just like your friend saying "no" to the trip.

⏳ Pending

Now we all know that one friend, who knows that he doesn't wanna come, but is too shy to tell that to you. Such friends won't say either "yes" or "no", and will simply try to delay the talk.

The pending state is just like that! It's the state the promise remains in until it gets finally resolved (meaning fulfilled or rejected).

Utility Methods

Promise.resolve()

So let's say you start calling your friends up one by one asking about the trip. Now in order to boost your confidence, you firstly reach out to your friend "Rahul" who has the following characteristics:

  • Chill parents

  • A lot of money (Like really a lot)

  • Always ready for anything

You absolutely know that this is my guy. He never says "no" to anything. And that is what happens! He replies immediately with:

"Bro I'm in."

No waiting at all.

Me after Rahul's reply:

Example Code:

const askRahul = Promise.resolve("Rahul Confirmed");

askRahul.then((data) => console.log(data));

Output:

Rahul Confirmed

Promise.reject()

After you feel a boost in your confidence, you decide to go straight to the final boss, your friend "Kunal". Kunal has a great track record. Out of all the trips your friends group has taken, Kunal has agreed to come onto one, because it was a short one-day trip 🙄. For all the other occasions, Kunal always has excuses like:

"Bro I have my exams"

"Bro my parents are not allowing"

You hit him up, and just like always, he replies with immediate rejection.

Example Code:

const askKunal = Promise.reject("Kunal busy (like always)");

askKunal
    .then((data) => {
        console.log("This block of code never gets executed");
    })
    .catch((data) => {
        console.log(data);
    });

Output:

Kunal busy (like always)

Concurrency Methods

Promise.all()

This method takes an iterable of promises as input, and returns a single Promise. This returned promise gets fulfilled only if all of the input promises fulfill. It gets rejected even if any one input promise rejects.

In our analogy, this method is like the scenario:

"Trip happens only if EVERYONE agrees"

Let's say you ask three of your friends: Rahul, Kunal and Dev. We go on a trip only if everyone agrees. If even one friend cancels, the trip is cancelled.

Example Code:

const askEveryone = Promise.all([askRahul, askKunal, askDev]);

askEveryone
    .then((data) => {
        console.log("Yo everyone said 'yes'!");
        console.log(data.join("\n"));
    })
    .catch((data) => {
        console.log("We can't go! Someone said 'no'.");
        console.log(data);
    });

Output:

We can't go! Someone said 'no'.
Kunal busy (like always)

Kunal be like:

Promise.allSettled()

This method takes an iterable of promises as input and returns a single Promise. This returned promise gets fulfilled simply when all of the input promises get completed. It doesn't matter whether they get fulfilled, or rejected. As long as all the input promises come out of their pending state, the returned promise of this method gets fulfilled.

In our analogy, this is like:

"Let’s see everyone’s status first"

You basically wanna see how many of your friends are agreeing to come, and how many or not. You don't cancel the trip automatically. You simply gather everyone's replies. You want a full report like this:

  • Rahul -> coming

  • Kunal -> busy

  • Dev -> coming

Example Code:

const askEveryone = Promise.allSettled([askRahul, askKunal, askDev]);

askEveryone
    .then((data) => {
        console.log("Here is what everyone said:\n");
        console.log(data);
    })
    .catch((err) => {
        console.log(err);
    });

Output:

Here is what everyone said:

[
  { status: 'fulfilled', value: 'Rahul Confirmed' },
  { status: 'rejected', reason: 'Kunal busy (like always)' },
  { status: 'fulfilled', value: 'Dev Confirmed' }
]

Promise.race()

This method takes an iterable of promises as input and returns a single Promise. The returned promise gets settled with the eventual state of the first promise that settles.

The definition may sound a bit complex, but it really isn't. In our analogy, this is basically like:

"We go with whoever replies first"

If the first person says "Let's go!", then the trip happens. However, if the first person says "I can't come", the trip is immediately cancelled.

Example Code:

const askEveryone = Promise.race([askRahul, askKunal, askDev]);

askEveryone
    .then((data) => {
        console.log("First Person agreed:");
        console.log(data);
    })
    .catch((data) => {
        console.log("First Person denied:");
        console.log(data);
    });

Output:

First Person agreed:
Rahul Confirmed

In this example, Kunal again tries to disagree:

But Rahul is already on you're side, and thus the trip is on! 😎

Promise.any()

This method also takes an iterable of promises as input and returns a single Promise. The returned promise gets fulfilled when any one input promise gets fulfilled. It gets rejected if all of the input promises get rejected.

In our analogy, this is simple like:

"We go as long as at least ONE friend can come"

So you can imagine this as the final desperate situation in your trip planning. You're so tired of your friends just saying "no" every time, that this time you're simply ready to go even if one single friend "agrees". However, if you have really bad luck, and everyone says "no", the trip gets cancelled, and you realize ZNMD is just a hypothetical movie.

Example Code:

const askEveryone = Promise.any([askRahul, askKunal, askDev]);

askEveryone
    .then((data) => {
        console.log("One Person agreed:");
        console.log(data);
    })
    .catch((data) => {
        console.log("Everyone denied:");
        console.log(data);
    });

Output:

One Person agreed:
Rahul Confirmed

Summary Table

Method Analogy
resolve Friend instantly agrees
reject Friend instantly denies
all Everyone must agree
allSettled Show me everyone’s status
race First reply decides
any First agreement decides

Conclusion

With this fun analogy, I don't think you will ever forget the different Promise methods. Planning a trip to Goa with your friends and working with Promises in JavaScript have something in common - uncertainty. You never know who will say “yes,” who will say “no,” or who will keep you waiting.

Whether you need everyone to agree (Promise.all), just one person to say yes (Promise.any), the first reply (Promise.race), or a complete status report (Promise.allSettled), JavaScript gives you precise control over asynchronous flow.

And just like Goa plans, sometimes everything works out perfectly… and sometimes Kunal ruins it.