Open In App

What is callback hell in Node.js ?

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

To know what is callback hell, we have to start with Synchronous and Asynchronous Javascript. 

What is Synchronous Javascript? In Synchronous Javascript, when we run the code, the result is returned as soon as the browser can do. 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 executed. 

What is Asynchronous Javascript?

  • Some functions in Javascript require AJAX because the response from some functions is not immediate. It takes some time and the next operation cannot start immediately. It has to wait for the function to finish in the background. In such cases, the callbacks need to be asynchronous.
  • Some external Javascript Web APIs allow AJAX – Asynchronous Javascript and XML. In AJAX, many operations can be performed simultaneously.

What is a callback?

  • Callbacks are nothing but functions that take some time to produce a result.
  • Usually, these async callbacks (async short for asynchronous) are used for accessing values from databases, downloading images, reading files, etc.
  • As these take time to finish, we can neither proceed to the 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 complete.

What is callback hell? 

This is a big issue caused by coding with complex nested callbacks. Here, each and every callback takes an argument that is a result of the previous callbacks. In this manner, The code structure looks like a pyramid, making it difficult to read and maintain. Also, if there is an error in one function, then all other functions get affected. 

Example: This is an example of typical callback hell. 

javascript




app.get("/details", function (req, res) {
    const name = req.query.name;
    console.log(name);
 
    Scopus.find({ name: name },
        { '_id': 0, 'authorId': 1 },
        function (err, result) {
            if (err) { }
            else {
                let searchResult = result[0]["authorId"];
                console.log(searchResult);
                let options = {
                    url: "https://api.elsevier.com/content/author/author_id/"
                        + searchResult + "?apiKey",
                    headers: { 'Accept': 'application/json' }
                };
                request(options, function (error, response, body) {
                    if (error) {
 
                        // Print the error if one occurred
                        console.error('error in Authors :', error);
 
                        // Print the response status code if a response was received
                        console.log('statusCode:', response && response.statusCode);
                        res.send("error")
                    }
                    else if (!error) {
                        let jsonObj = JSON.parse(body);
                        if (jsonObj['author-retrieval-response'] == undefined) {
                            res.send("No details");
                        }
                        else {
                            let reqData = jsonObj['author-retrieval-response'][0];
                            let authprofile = reqData["author-profile"]
                            let names = authprofile["preferred-name"]["indexed-name"]
                            console.log(names);
                            let citation = reqData["coredata"]["citation-count"];
                            let query = { authorId: searchResult };
 
                            Scopus.findOneAndUpdate(query, {
                                name: names,
                                citationCount: citation
                            }, function (err, doc, res) {
                                if (err) {
                                    console.log("error");
                                }
                                else {
                                    console.log("success");
                                }
                            })
                            res.render("details", { data: reqData });
                        }
                    }
                });
            }
        })
});


You can notice the nested callbacks look like a pyramid which makes it difficult to understand.

 How to escape from a callback hell?

  • JavaScript provides an easy way of escaping from callback hell. This is done by event queue and promises.
  • A promise is a returned object from any asynchronous function, to which callback methods can be added based on the previous function’s result.
  • Promises use .then() method to call async callbacks. We can chain as many callbacks as we want and the order is also strictly maintained.
  • Promises use .fetch() method to fetch an object from the network. It also uses .catch() method to catch any exception when any block fails.
  • So these promises are put in the event queue so that they don’t block subsequent JS code. Also once the results are returned, the event queue finishes its operations.
  • There are also other helpful keywords and methods like async, wait, set timeout() to simplify and make better use of callbacks.


Last Updated : 03 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads