Skip to main content

Command Palette

Search for a command to run...

JavaScript Callbacks and Callback Hells

Day 12

Published
3 min readView as Markdown
JavaScript Callbacks and Callback Hells

In this blog post, I will explain what callbacks are and how they can lead to callback hells in JavaScript. I will list some ways to avoid or deal with callback hells using promises, async/await, and other techniques which we will discuss in the next blog.

What are callbacks?

A callback is a function that is passed as an argument to another function and is executed after the other function finishes. For example, if you want to perform some operation on a file, you can use the fs.readFile() function in Node.js and pass a callback function that will run after the file is read:

fs.readFile('example.txt', 'utf8', function(err, data) { // this is the callback function 
    if (err) { 
        console.error(err); 
    } else { 
        console.log(data); 
    } 
});

The callback function takes two parameters: err and data. The err parameter will contain an error object if something went wrong while reading the file, and the data parameter will contain the file content as a string.

Why use callbacks?

Callbacks are useful for handling asynchronous operations, such as reading files, making HTTP requests, or interacting with databases. Asynchronous operations are those that do not block the execution of the code and allow other tasks to run in the meantime. For example, when you read a file, you don't have to wait until the file is loaded before you can do something else. You can pass a callback function that will handle the file content when it is ready.

What are callback hells?

Callback hells are situations where you have multiple nested callbacks that make the code hard to read, understand, and maintain. For example, suppose you want to read three files in a specific order and then write their content to a new file. You might end up with something like this:

fs.readFile('file1.txt', 'utf8', function (err1, data1) {
  if (err1) {
    console.error(err1);
  } else {
    fs.readFile('file2.txt', 'utf8', function (err2, data2) {
      if (err2) {
        console.error(err2);
      } else {
        fs.readFile('file3.txt', 'utf8', function (err3, data3) {
          if (err3) {
            console.error(err3);
          } else {
            fs.writeFile('newfile.txt', data1 + data2 + data3, 'utf8', function (err4) {
              if (err4) {
                console.error(err4);
              } else {
                console.log('Success!');
              }
            });
          }
        });
      }
    });
  }
});

As you can see, this code is very messy and hard to follow. It also has a lot of repetition and error handling. This is the case with only 4 functions, consider what would be the case if we had 50 functions to be nested like this. This is an example of a callback hell.

How to avoid or deal with callback hells?

There are several ways to avoid or deal with callback hells in JavaScript. Some of them are:

  • Use named functions instead of anonymous functions. This will make the code more readable and easier to debug.

  • Use promises. Promises are objects that represent the outcome of an asynchronous operation. They have two methods: then() and catch(), which allow you to chain callbacks and handle errors in a cleaner way.

  • Use async/await. Async/await is a syntactic sugar that lets you write asynchronous code as if it was synchronous. You can use the await keyword to wait for a promise to resolve and assign its value to a variable. You can use the async keyword to declare a function that returns a promise.

Conclusion

In this blog post, we have seen what callbacks are and how they can lead to callback hells in JavaScript. I have also listed some ways to avoid or deal with callback hells using promises, async/await, and other techniques. We will see these techniques in more detail in the next blog. I hope you have learned something useful and enjoyed reading this post.