The JS Bifrost — Callback Hell

You need to know to deal with this hell, to Rise above the Cliché!

Ashmit Bhatnagar
Globant
7 min readSep 21, 2020

--

Welcome to The JS Bifrost, your pathway to the rock-solid foundation for God-level JavaScript. This article is all about how to avoid ‘Callback Hell’ and how to deal with it.

The way to God-level JavaScript is not easy. It takes more than just being a good problem solver. Clean and efficient code will any day give you an edge above the others.

In this article, we’ll discuss Callbacks and how to deal with the situation of Callback Hell. Callback hell is an enemy of clean and efficient code.

Knowing how to deal with this hell, will take you one step forward on the Bifrost to God Level JS!

Let’s start with the component that this hell is made up of.

Callbacks

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete its action. They’re so common in JavaScript that you probably have used callbacks yourself without knowing that they’re called callbacks.

A very simple example of the callback is:

In this case, getLessThanTen is the callback. Array.filter is a function is an acceptor of a callback function.

Callback functions are everywhere once you know what they are!

Callbacks are used in two ways — in synchronous functions and asynchronous functions. In Synchronous functions, when you want a part of the code to be swapped with something else. In Asynchronous functions, when JavaScript needs to wait for something to complete, and execute the rest of the tasks given to it while waiting.

The biggest hurdle people face when trying to understand callbacks is understanding the order in which statements execute as the program runs. This majorly happens in Asynchronous codes.

The problem in Javascript is that the only way to “pause” a computation and have “the remaining” execute asynchronously is to put “the remaining” inside a callback.

For example, say I want to run code the following code:

What happens if now I want to make the above functions asynchronous, meaning that I get want to run some other code while I am waiting for them to return their values?

In Javascript, the way to do it is using continuation passing style:

The above code gets uglier with every increase in callbacks. See the pyramid shape and all the closing braces at the end? This is known as Callback Hell.

Callback Hell

Callback hell is a block where the use of function callbacks in asynchronous code becomes obscure or difficult to follow. Usually, when there is more than one level of indirection, code with callbacks become difficult to follow, refactor and test.

This is how your code might look like, a Pyramid of Doom!

If you had a file full of these, even God of JavaScript would not be able to save you! Why?

Because when you have lots of callback functions in your code it gets harder to work with them.

Callback Hell occurs because in JavaScript the only way to delay a computation, so that it runs after the asynchronous call returns, is to put the delayed code inside a callback function.

You cannot delay a code that was written in a synchronous style, so you’ll need nested callbacks.

Let’s create a callback hell of our own and then learn the methods to deal with it.

Constructing a Callback Hell

Let’s imagine we are trying to make a sandwich. To make a sandwich, we need to go through the following steps:

  1. Get patty
  2. Cook the patty
  3. Get the bread
  4. Put the cooked patty between the bread
  5. Serve the sandwich

These steps are asynchronous. We have to wait for one step to finish until we proceed with another. To wait for something in JavaScript means, we need to use a callback.

To make the sandwich, we have to make the patty first. We can only cook the patty after we get the patty from the fridge.

To cook the patty, we need to pass patty into the cookPatty function. Then, we have to wait for the patty to get cooked.

Once the patty gets cooked, we get the bread.

After we get the bread, we need to put the patty between the pieces of bread.

We can’t return sandwich from makeSandwich because it’s asynchronous. We need to accept a callback to serve the sandwich.

Solutions to Callback Hell

There are 4 solutions:

  1. Using Comments
  2. Modularise
  3. Using Promises
  4. Using Async/Await

First Solution: Using Comments

The makeSandwich callback hell is simple to understand. But, if you’re reading makeSandwich for the first time, you may think “Why do we need so many callbacks to make a sandwich? It doesn’t make sense!”.

In such a case, we can leave comments to explain our code.

But this gives us a reason why we had to write this type of code (Pyramid of Doom). It doesn’t ease your pain of refactoring, testing and maintaining it.

Second Solution: Modularise

We need to modularise our code so that it is easier to keep track of.

For getPatty, our first callback, we have to go to the fridge to get the patty. There are two fridges in the kitchen. Our patty is in the right fridge.

Now imagine if you have to write each of these steps in makeSandwich , you’ll probably faint with the sheer amount of code!

Third Solution: Using Promises

Promises make callback hell much easier to manage. Instead of the nested code, you’ll have this:

This is so much easier to read, understand and manage.

Fourth solution: Async/Await

With Async/Await, you can write makeSandwich as if it’s synchronous again!

So easy right?

Callback Hell is not that big a problem after you see Promises and Async/Await.

Yes, they are a blessing! If you know how to use them wisely, you can really keep your code easier to follow, easier to refactor, and easier to test.

Closing Thoughts

Promises and Async/Await are a great boon when you have to deal with Callback Hell. Writing comments and modularising the code are good solutions but only for small programs. As your code becomes large both of them will fail.

“You’re building your own maze, in a way, and you might just get lost in it.”
Marijn Haverbeke, Eloquent JavaScript

Asynchronous JavaScript can be a maze of its own. But now you know the tools to deal with it and get out of the maze easily.

--

--