Skip to main content

Command Palette

Search for a command to run...

Keeping up with your Promise()

Updated
5 min read
Keeping up with your Promise()

Promise is an object whose value we don't know currently but will know in the near future. Now I am well aware that this sounds a bit off, but hang on, this will make sense after this example. Let's say I promise to make a burger for you and currently since I haven't prepared one, the status of this promise is pending and value is undefined.

Let's run through all the ingredients to make a burger!

  1. Buns
  2. Patty
  3. Cheese

These are the elements required to fulfil my promise of making a burger. Let's put these ingredients in an array called Basket.

const basket = ['buns',' patty', 'coffee', 'cheese', 'book']

Now since I've got my ingredients ready in basket, I will grab them from my basket and prepare a burger for you as I promised! 🍔 Hence, the status of this promise is fulfilled and the value is Burger! If by any means one of the three ingredients would be missing, my promise wouldn't be fulfilled so, the status will be "reject" and the value would have some kinda error message explaining why the promise wasn't fulfilled.

Enough of analogies, let's dive straight into code to understand the working of promise!

Firstly let us define a promise,

new Promise((resolve, reject)=>{

})

Here a callback function is passed to promise to work on with parameters resolve and reject. Resolve and reject are methods, one of which is executed depending on whether the promise is fulfilled or not. We will write an if condition inside the callback function to check if my required ingredients are present or not, and depending on that resolve() or reject() method will be invoked; which takes a string as an argument.

const burgerPromise = new Promise((resolve,reject)=>{
    if(basket.includes("buns")&& basket.includes("patty")&& basket.includes("cheese")){
        resolve("Burger🍔");
    }else{
        reject("ingredient missing");
    }
})

Here, we have successfully created or produced a promise and contained it into a variable called burgerPromise. Now we will find a way to utilise or consume it.

burgerPromise.then((food)=>{
        console.log(`Here is the ${food} I promised.`);
    },
    (error)=>{
        console.log(`${error} so promise is rejected.`);
    }
)

Like we can see in the code, then() is taking 2 callback functions separated by a comma! The first callback function is invoked if the promise is fulfilled and the second is invoked if the promise is rejected.

Here, the string that was given to resolve() is passed to the first callback function of then method as a parameter, and the same would apply to reject() in case the if condition would turn out to be false.

💡 Note: It is not mandatory that then() have 2 callback functions, we can only care about the resolve case and ignore the reject case; vice versa.

We can use the catch() method, instead of passing two callbacks in then().

burgerPromise.then((food)=>{
        console.log(`Here is the ${food} I promised.`);
    }
).catch((error)=>{
        console.log(`${error} so promise is rejected.`);
    }
)

So here, .then() handles the resolve part of the promise and .catch() handles the reject part of the promise.


Now we must keep in mind that Promise works asynchronously! In simpler words, the browser handles the promise, not the Javascript engine. To demonstrate this we can simply add a console.log() after promise.

burgerPromise.then((food)=>{
        console.log(`Here is the ${food} I promised.`);
    }
).catch((error)=>{
        console.log(`${error} so promise is rejected.`);
    }
)

for(i=0;i<=10;i++){
    console.log(i)
}

Here promise will be held in the microtask queue until Global Execution Context is done executing and leaves the callstack empty.

I will let you copy-paste the code and see the output yourself! 🙂


Now, the manner in which promise is executed reminds me of setTimeout(), which also waits for the callstack to be empty and then brought into execution from the callback queue by the event loop. The question that arises is, what if we have a promise and setTimeout in the same program?

console.log('start')

burgerPromise.then((food)=>{
        console.log(`Here is the ${food} I promised.`);
    }
).catch((error)=>{
        console.log(`${error} so promise is rejected.`);
    }
)

setTimeout(()=>{
    console.log('Inside setTimeout!')
},0)

console.log('end')

If we run this, we will find that the microtask queue has a higher priority than the callback queue. Hence, considering the promise is resolved, the output will be:

start
end
Here is the Burger🍔 I promised.
Inside setTimeout!

Function returning a promise

In case, we want a function built around our promise can simply do this:

function MyBurger(){
    const basket = [buns, patty, coffee, cheese, book];
    return new Promise((resolve,reject)=>{
        if(basket.includes("buns")&& basket.includes("patty")&& basket.includes("cheese")){
            resolve("Burger🍔");
        }else{
            reject("ingredient missing");
        }
    })
}

//its simply invoking the function and accessing the promise methods
MyBurger().then((food)=>{
        console.log(`Here is the ${food} I promised.`);
    }
).catch((error)=>{
        console.log(`${error} so promise is rejected.`);
    }
)

Promise chaining

Before we learn chaining in promise we must know what Promise.resolve() is. Its easier to understand with this example:

const burger = Promise.resolve("Burger");
burger.then(food=>{
    console.log(`Here is the ${food} i promised.`);
})

// it can also be written without storing the Promise into a variable
Promise.resolve("Burger").then(food=>{
    console.log(`Here is the ${food} i promised.`);
})

//both would give the same output

It is pretty much self-explanatory with the example shown above.

The thing I am yet to tell you is, then() always returns a new Promise at the end! To demonstrate this we will have a look at this example.

function MyBurger(){
    return new Promise((resolve, reject)=>{
        resolve("veg");
    })
}

MyBurger()
    .then((food)=>{
        console.log(food);
        food += " burger";
        return food;
    })
    .then((food)=>{
        console.log(`Here is your ${food}`)
    })

Here, what you are seeing for the first time is what's called Promise chaining, i.e. when we see a bunch of .then() one after the other! To a normal eye it seems that the first then() is returning a variable called food containing the string "veg burger" , but like I have said "then() always returns a new Promise at the end!", what is actually returned to the next then() is Promise.resolve(food) which results in the following sentence:

Promise.resolve(food).then((food)=>{
    console.log(`Here is your ${food}`)
})

That's all for now. I truly hope you have learned Promise() thoroughly and found this article helpful.


I plan to write more often, as it gives me a better understanding of the topic which to write about.

You can find me on Twitter(@Pritam Debnath) do reach out to share your thoughts, suggestions, and anything you want to have a conversation about.