Callback and Promises in JavaScript

Serajur Reza Chowdhury
4 min readOct 9, 2020

In JavaScript, functions are first class objects. Which means they can be passed as arguments, they can have properties and methods like objects. In JavaScript, function are the type of object. They can be stored in variables, created and returned from functions.

Callback

Callback functions are something that a function returns as a response during being called. Here a function is passed as a parameter inside another function.

In asynchronous programming, a piece of code does not sit idle. It keeps executing. But it has a problem. We don’t know when we will get our task done, such as data retrieving from api, storing data in database etc. These are all asynchronous execution.

Callback takes care of asynchronous execution. Meaning that where there is a blocking code(a piece of code which stops execution of a code until it itself gets executed), it does not stop the whole code being executed.

A normal callback function example,

const processName=(name)=>{console.log(name)}const showName=(name , callBack)=>{callBack(name)}showName("Raphael", (name)=>{processName(name)})console.log("Hello")//output://Raphael//Hello

In this code, we have a showName method which takes a name and a callback as a parameter. The callback itself also takes a name as a parameter. While executing showName the callback function gets executed. It prints “Raphael”. Then the console.log(“Hello”) executed, which prints “Hello”.

For Asynchronous code

const processName=(name)=>{console.log(name)}const showName=(name , callBack)=>{callBack(name)}showName("Raphael", (name)=>{setTimeout(()=>{processName(name)},3000)})console.log("Hello")//output//Hello//Raphael

In this code, showName starts execution and then it sees setTimeout, which is an asynchronous code. It goes to the web api, then the rest of the code gets executed. Which is why “Hello” is printed first. Then comes the asynchronous code in web api. It goes to callback queue, then event loop takes it back to call stack and then it gets executed. So, then it prints “Raphael”.

Aynchronous execution details can be found in this article -

https://medium.com/@rezainfinity54/synchronous-blocking-javascript-problems-and-its-solutions-asynchrous-non-blocking-way-fadd66ab71b

Callback Hell

Imagine this scenario,

showName("Raphael", (name)=>{showName1("Raphael", name)=>{showName2("Raphael", name)=>{showName3("Raphael", name)=>{showName4("Raphael", name)=>{processName(name)}}}}})

Causing pain in the eye? Certainly for me.

You see that there one after one callbacks, which makes a code messy. It is really difficult to find out the execution point of the code, especially in apps.

Every problem has solution. The solution for this problem is Promise.

Promise

Promise is nothing but gives us a promise if certain condition is true. If the condition is true, then the promise will be resolved, if not then rejected.

It is used to handle the result of an asynchronous result. Promise can used to block the execution of a piece of code.

Let’s look at an example,

const hasMeeting = false;const meeting= new Promise((resolve, reject)=>{if(!hasMeeting){const meetingDetails= {name: "Technial Meeting",location: "Zoom",time: "06.00 PM"};resolve(meetingDetails);}else{reject(new Error("Meeting already scheduled"))}})meeting.then((res)=>{console.log(JSON.stringify(res))}).catch((err)=>{console.log(err.message)})console.log("Hello")//Hello//{"name":"Technial Meeting","location":"Zoom","time":"06.00 PM"}

Here we will use a variable “hasMeeting” to use inside our promise. Then we declare a promise which takes a resolve and reject as parameter. Resolve returns as success result from a promise and reject returns an error. If hasMeeting is false it returns an object “meetingDetail”. Otherwise it returns an error.

Now, using the promise, we use then() and catch() method in a body. Then() is executed when the promise returns a resolve and catch() is executed when the promise returns an error.

Only one gets executed based on whether resolve or reject is returned.

We can have multiple then(), catch() methods. The one which first satisfies the condition will be returned.

const hasMeeting = false;const meeting= new Promise((resolve, reject)=>{if(!hasMeeting){const meetingDetails= {name: "Technial Meeting",location: "Zoom",time: "06.00 PM"};resolve(meetingDetails);}else{reject(new Error("Meeting already scheduled"))}})const addtoCalender=(meetingDetails)=>{return new Promise((resolve, reject)=>{const calender= `meeting okay`resolve(calender)})}meeting.then(addtoCalender).then((res)=>{console.log(JSON.stringify(res))}).catch((err)=>{console.log(err.message)}).catch((error)=>{console.log("no")})//Hello//"meeting okay"

Promises are always asynchronous. That’s why it always returns its result in the end.

Handling multiple promises

Promise.all([p1,p2,….])

const p1= Promise.resolve("Promise 1 done")const p2= new Promise((resolve, reject)=>{setTimeout(()=>{resolve("Promise 2 done")},2000)})Promise.all([p1,p2]).then((res)=>{console.log(res)})//output//[ 'Promise 1 done', 'Promise 2 done' ]

It returns an array of resolve or reject. After the completion of execution whether based on time or not, it pushes all the promises in an array and returns it.

Promise.race([p1,p2,….])

const p1= Promise.resolve("Promise 1 done")const p2= new Promise((resolve, reject)=>{setTimeout(()=>{resolve("Promise 2 done")},2000)})Promise.race([p1,p2]).then((res)=>{console.log(res)})// Promise 1 done

It creates a race between the promises. After the execution finishes it returns the winner of the race, the promise who returned first.

--

--

Serajur Reza Chowdhury

Software Engineer, curious JavaScript programmer, love to share concepts.