Callbacks, Promises & Async/Await

Ishara Sandeepanie
5 min readOct 19, 2020

--

This is going to talk on callback functions, callback hell, how to resolve this callback hell problem using promises and async/awiat using JavaScript.

First of all, I’ll give a breif introduction of synchronous and asynchronous JavaScript.

In Synchronous Javascript, when we run the code, only one operation can happen at a time because it is single-threaded. So, all other processes are put on hold while an operation is executing.

In Asynchronous Javascript, when we run the code, multiple operations are executed simultenously.

For more information, you can refer my previous article which is regarding JavaScript asynchronous and synchronous behaviours.

  1. Callback Functions

Callbacks are nothing but functions that take some time to produce a result. A callback function is usually used as a parameter to another function. Usually these async callbacks are used for accessing values from databases, downloading images, reading files etc. As these take time to finish, we can neither proceed to next line because it might throw an error saying unavailable nor we can pause our program. So we need to store the result and call back when it is completed.

Lets try out examples of callback functions.

synchronous JavaScript code and output

This is a simple example for callback function in synchronous JavaScript. So, it is executed line by line. Inside the forEach() method an anonymous function is called as a parameter.

asynchronous JavaScript code and output

This is an example for asynchronous callback function. The setTimeout() is an asynchronous function. As we can see, the second() function only runs after 2 seconds because of the callback function on the setTimeout() function. While the download is happening, the executions of the first() function continue.

Sometimes you have a series of tasks where each step depends on the results of the previous step. This is a very straightforward thing to deal with in synchronous code. But when you try to do this in asynchronous code, it’s easy to run into callback hell, a common problem where you have callback functions deeply nested inside of each other. In this manner, the code structure looks like a pyramid.

Let’s understand through an example by using set timeout API which is asynchronous function, lets assume we have an employee detail API and we need to get all IDs and after details of a perticular ID. So your code will be as follows:

callback hell

This kind of code is difficult to read and can be a real pain to try to reorganize whenever you need to make changes to it. If you have deeply nested callbacks like this, it is usually a good idea to arrange the code differently. Promises and async/await are introduced as the solutions for this problem.

2. Promises

Promises are a popular way of getting rid of callback hell. The idea is that instead of using functions that accept input and a callback, we make a function that returns a promise object, that is, an object representing a value that is intended to exist in the future.

We can produce or consume promises. When we produce a promise, we create a new promise and send a result using that promise. When we consume a promise, we use callback functions for the fulfilled and rejected states of that promise.

promise and output

In the example above, we are producing a promise that looks for the IDs of employees. You may notice that the promise object receives a callback function that accepts two arguments: resolve and reject. This callback is called an executor function, and it is called immediately when the promise is created.

Once we have a function that returns a promise, we can use the .then() method on it to specify what should happen once resolve() or reject() is called.

Well then, the basic principle of the promises to end callback hell are:

  • A promise will gain control over the results of callbacks: resolve() and reject() functions.
  • All promise objects have the then() method.

Promises have a great advantage (if used correctly) called chaining. With chaining, we can simply add a new then() method after a then(). This gives us greater control over our chain of resolved promises.

Now lets see how the above callback hell is resolved through promise.

callback hell is resolved using promises

3. Async/Await

Async /await is another alternative for consuming promises. This is a new way of writing promises that are based on asynchronous code but make asynchronous code look and behave more like synchronous code.

We created an async function using the async keyword before the function. This means that this function is asynchronous, which means it basically runs in the background.

An async function may have one or more await expressions, so what we did was to consume our promises with the expression await, which returns the result of our resolved function called through the promise.

Lets write the above promise using async/await.

callback hell is resolved using async/await

So, through this post, I gave a brief introduction of callback functions, callback hell, promises and async/await. For more information, you can refer following refernces as well.

Thank You…..

--

--

No responses yet