{"id":1302,"date":"2016-06-12T14:50:23","date_gmt":"2016-06-12T09:20:23","guid":{"rendered":"http:\/\/code.ciphertrick.com\/?p=1302"},"modified":"2016-06-12T14:50:23","modified_gmt":"2016-06-12T09:20:23","slug":"avoiding-callback-hell-node-js","status":"publish","type":"post","link":"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/","title":{"rendered":"Avoiding callback hell in Node.js"},"content":{"rendered":"\n<p><b>Callback hell<\/b> is a phenomenon that afflicts a JavaScript developer when he tries to execute multiple asynchronous operations one after the other. Some people call it to be the <b>pyramid of doom<\/b>.<br>\nLet&#8217;s have a look at an example of what we call callback hell.<\/p>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\ndoSomething(param1, param2, function(err, paramx){<br>\n    doMore(paramx, function(err, result){<br>\n        insertRow(result, function(err){<br>\n            yetAnotherOperation(someparameter, function(s){<br>\n                somethingElse(function(x){<br>\n                });<br>\n            });<br>\n        });<br>\n    });<br>\n});<br>\n<\/code><\/p>\n\n\n\n<p><b>Note-<\/b> The above code is for demonstration and not a working code.<\/p>\n\n\n\n<p>This is looking bad just from the skeleton itself. In real code you will obviously have other statements like <kbd>if<\/kbd>, <kbd>for<\/kbd> or some other operations along with these nested functions. Add those to the above code and it would get really messy and unmanageable.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Pro_Tip\" >Pro Tip<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Techniques_for_avoiding_callback_hell\" >Techniques for avoiding callback hell<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Managing_callbacks_using_Asyncjs\" >Managing callbacks using Async.js<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Installation\" >Installation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#asyncwaterfall\" >async.waterfall()<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#asyncseries\" >async.series()<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Managing_callbacks_using_promises\" >Managing callbacks using promises<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Chaining_promises\" >Chaining promises<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Changing_callbacks_to_promises\" >Changing callbacks to promises<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Writing_functions_that_work_with_promises\" >Writing functions that work with promises<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/thrivemyway.com\/avoiding-callback-hell-node-js\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Pro_Tip\"><\/span>Pro Tip<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Do not overload your functions. Most of the times it might be possible that the real problem you are facing is not the <b>callback hell<\/b>, rather it&#8217;s poorly written functions. In such cases, the solutions we will see below would structure your code but they won&#8217;t solve your real problem. So, as a rule of thumb, make your function do less, meaning write small functions that accomplish a single task.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Techniques_for_avoiding_callback_hell\"><\/span>Techniques for avoiding callback hell<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>There are multiple techniques for dealing with callback hell. In this tutorial, we will have a look at the below two in particular.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Using Async.js<\/li>\n\n\n\n<li>Using Promises<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Managing_callbacks_using_Asyncjs\"><\/span>Managing callbacks using Async.js<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p><b>Async<\/b> is a really powerful npm module for managing asynchronous nature of JavaScript. Along with Node.js, it also works for JavaScript written for browsers.<\/p>\n\n\n\n<p>Async provides lots of powerful utilities to work with asynchronous processes under different scenarios.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Installation\"><\/span>Installation<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nnpm install --save async<br>\n<\/code><br>\n&nbsp;<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"asyncwaterfall\"><\/span>async.waterfall()<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>For our problem, we will be looking at two functions of async in particular. i.e <kbd>async.waterfall()<\/kbd> and <kbd>async.series()<\/kbd>.<br>\nAsync Waterfall is useful when you want to execute some tasks one after the other and at the same time pass on the result from the previous task to the next.<\/p>\n\n\n\n<p><kbd>async.waterfall()<\/kbd> takes in an array of functions &#8216;<kbd>tasks<\/kbd>&#8216; and a final &#8216;<kbd>callback<\/kbd>&#8216; function which is called after all the functions in <kbd>tasks<\/kbd> have completed or a <kbd>callback<\/kbd> is called with an error.<br>\nHave a look below for better understanding.<\/p>\n\n\n\n<div class=\"head-align\">Async Waterfall<\/div>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nvar async = require('async');<br>\nasync.waterfall([<br>\n    function(callback) {<br>\n        \/\/doSomething<br>\n        callback(null, paramx); \/\/paramx will be availaible as the first parameter to the next function<br>\n        \/**<br>\n            The 1st parameter passed in callback.<br>\n            @null or @undefined or @false control moves to the next function<br>\n            in the array<br>\n            if @true or @string the control is immedeatly moved<br>\n            to the final callback fucntion<br>\n            rest of the functions in the array<br>\n            would not be executed<br>\n        *\/<br>\n    },<br>\n    function(arg1, callback) {<br>\n        \/\/doSomething else<br>\n      \/\/ arg1 now equals paramx<br>\n        callback(null, result);<br>\n    },<br>\n    function(arg1, callback) {<br>\n        \/\/do More<br>\n        \/\/ arg1 now equals 'result'<br>\n        callback(null, 'done');<br>\n    },<br>\n    function(arg1, callback) {<br>\n        \/\/even more<br>\n        \/\/ arg1 now equals 'done'<br>\n        callback(null, 'done');<br>\n    }<br>\n], function (err, result) {<br>\n    \/\/final callback function<br>\n    \/\/finally do something when all function are done.<br>\n    \/\/ result now equals 'done'<br>\n});<br>\n<\/code><\/p>\n\n\n\n<p>So using <kbd>async.waterfall()<\/kbd>, you would be writing you code vertically instead of indenting it horizontally and entering the pyramid of doom. Plus your code would be much more organized and easy to read.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"asyncseries\"><\/span>async.series()<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>Async provides another function for handling execution in series, <kbd>async.series()<\/kbd>. Async series works in a similar way to Async waterfall, by executing functions in the array one after the other with the difference that it won&#8217;t pass the data from one function to another, instead when all the functions have completed their execution the result of the functions will be available in the final callback as an array. Similar to <kbd>async.waterfall()<\/kbd> in <kbd>async.series()<\/kbd> as well, when any of the functions is called with an error callback, no more functions in the array are executed and the final callback is immediately called with the value of the error. Have a look below for a clear picture.<\/p>\n\n\n\n<div class=\"head-align\">Async Series<\/div>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nvar async = require('async');<br>\nasync.series([<br>\n    function(callback){<br>\n        \/\/ do some stuff ...<br>\n        callback(null, 'one');<br>\n        \/**<br>\n            The 1st parameter passed in callback.<br>\n            @null or @undefined or @false control moves to the next function<br>\n            in the array<br>\n            if @true or @string the control is immedeatly moved<br>\n            to the final callback fucntion with the value of err same as<br>\n            passed over here and<br>\n            rest of the functions in the array<br>\n            would not be executed<br>\n        *\/<br>\n    },<br>\n    function(callback){<br>\n        \/\/ do some more stuff ...<br>\n        callback(null, 'two');<br>\n    }<br>\n],<br>\n\/\/ optional callback<br>\nfunction(err, results){<br>\n    \/\/ results is now equal to ['one', 'two']<br>\n});<br>\n<\/code><br>\n&nbsp;<br>\nThere are more cool functions availaible with the async module make sure you check them out and use it in your Node.js projects.<br>\nVisit the Github page here: <a href=\"https:\/\/github.com\/caolan\/async\" target=\"_blank\" rel=\"nofollow noopener\">Async.js Github<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Managing_callbacks_using_promises\"><\/span>Managing callbacks using promises<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Promises are alternative to callbacks, while dealing with asynchronous code. Promises return the value of the result or an error exception. The core of the promises is the <kbd>.then()<\/kbd> function, which waits for the promise object to be returned. The <kbd>.then()<\/kbd> function takes two optional functions as arguments and depending on the state of the promise only one will ever be called. The first function is called when the promise if fulfilled (A successful result). The second function is called when the promise is rejected.<br>\nLet us see the structure of a typical promise.<\/p>\n\n\n\n<div class=\"head-align\">Promises<\/div>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nvar outputPromise = getInputPromise().then(function (input) {<br>\n    \/\/handle success<br>\n}, function (error) {<br>\n    \/\/handle error<br>\n});<br>\n<\/code><br>\n&nbsp;<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Chaining_promises\"><\/span>Chaining promises<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>We can also chain promises, this is an equivalent alternative to nesting callbacks. There are two ways to chaining promises. Promises can be chained inside or outside the handlers (.then() function). Chaining promises outside the handle is much clean and easy to read but we may have to chain promises inside the handler if we want to use some parameter in our next handler which available in the scope of the previous handler. Although too much chaining inside the handler will again result in horizontal code which we are trying to avoid. We can also chain promises with a combination of inside and outside chains. As a general rule, I would recommend you to avoid chaining inside the handler.<\/p>\n\n\n\n<div class=\"head-align\">Chaining Promises<\/div>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nreturn getUsername().then(function (username) {<br>\n    return getUser(username);<br>\n})<br>\n.then(function (user) { \/\/example of chaining outside the handler<br>\n   return userPassword().then(function(password){<br>\n        \/**<br>\n            example of chaining inside the handler,<br>\n            since we need to use the @user param<br>\n            from the previous handler scope<br>\n        *\/<br>\n        if(user.password !== password){<br>\n            \/\/reject promise or throw error<br>\n            return;<br>\n        }<br>\n    });<br>\n});<br>\n<\/code><br>\n&nbsp;<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Changing_callbacks_to_promises\"><\/span>Changing callbacks to promises<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>There are a few good libraries for promises, we will look at the examples from the popular <b>Kriskowal&#8217;s q<\/b> promises library. Make sure you have q installed.<\/p>\n\n\n\n<p><kbd>npm install --save q<\/kbd><\/p>\n\n\n\n<div class=\"head-align\">callbacks to promises<\/div>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nvar fs = require('fs');<br>\nvar Q = require('q');<br>\nvar readFile = Q.nfbind(fs.readFile);<br>\nreadFile(\"foo.txt\", \"utf-8\").then(function (text) {<br>\n   \/\/handle success<br>\n}, function(err){<br>\n   \/\/handle error<br>\n});<br>\n<\/code><br>\n&nbsp;<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Writing_functions_that_work_with_promises\"><\/span>Writing functions that work with promises<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>We can also write our own function that works with promises. Look at the example below.<\/p>\n\n\n\n<div class=\"head-align\">functions that work with promises<\/div>\n\n\n\n<p><code lang=\"javascript\" class=\"javascript\"><br>\nvar fs = require('fs');<br>\nvar Q = require('q');<br>\n\/\/creation<br>\nfunction read(file) {<br>\n    var deferred = Q.defer();<br>\n    fs.readFile(file, 'UTF-8', function(err, data){<br>\n        if(err) {<br>\n            deferred.reject(err); \/\/faliure, control will return to the second function<br>\n        } else {<br>\n            deferred.resolve(data) \/\/ fulfills the promise and returns data as value<br>\n        }<br>\n    });<br>\n        return deferred.promise \/\/ our mthod returns promise<br>\n}<br>\n\/\/usage<br>\nread('demo.txt').then(function(data){<br>\n    \/\/promise resolved with data<br>\n}, function(err){<br>\n    \/\/promise rejected with err<br>\n});<br>\n<\/code><br>\n&nbsp;<br>\nThere is more to promises, headover to the <a href=\"https:\/\/github.com\/kriskowal\/q\" target=\"_blank\" rel=\"nofollow noopener\">Github<\/a> page to find out more.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Thus, we have seen, how we can deal with the problem of callback hell in Node.js. There are a few more ways to solve the problem like using generators, modularization etc. But we feel that <b>async<\/b> and <b>promises<\/b> are the two de-facto solutions for dealing with callback hell, with async preferred more over promises. However, remember what we discussed earlier, your core problem might just not be the callback hell, it could be poorly written functions. Make sure you keep your functions skinny and focused on a single task. You will learn more about async and promises only when you will use them. So make sure you try them out next time in your projects.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Callback hell is a phenomenon that afflicts a JavaScript developer when he tries to execute multiple asynchronous operations one after [&hellip;]<\/p>\n","protected":false},"author":3000066,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3001974,3001977],"tags":[],"class_list":["post-1302","post","type-post","status-publish","format-standard","hentry","category-javascript","category-node-js-2"],"acf":[],"_links":{"self":[{"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/posts\/1302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/users\/3000066"}],"replies":[{"embeddable":true,"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/comments?post=1302"}],"version-history":[{"count":0,"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/posts\/1302\/revisions"}],"wp:attachment":[{"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/media?parent=1302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/categories?post=1302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thrivemyway.com\/wp-json\/wp\/v2\/tags?post=1302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}