Thursday, October 22, 2015

Callbacks in Javascript

In today's blog post, I will be talking about what callback functions are and their advantages and disadvantages in JavaScript. Callback is a functional programming technique which allows the use of functions as arguments.

Callback Functions

Simply stated, a callback is a function that is passed as an argument to another function. For example,

setTimeout(function() {
    console.log('abhi');
}, 2000);                     //prints 'abhi' after 2 seconds

In the above example, we used a function which just logs one word to the console. The function passed to setTimeout function is the callback function. setTimeout is an inbuilt function in JavaScript which executes the argument function after specified number of milliseconds.
We can pass callbacks either anonymously (as above example) or as a named function (as shown below).




setTimeout(logger, 2000);
var logger = function() {
    console.log('abhi');  //prints 'abhi' after 2 seconds
} 

This code sample does the same thing as one above, except this time named function is used.

Writing own callbacks

We can easily write our own callbacks. Here, we created a simple objLogger function which prints all the object's own properties and their corresponding values. This objLogger function is then used as a callback. The changeName function simply executes the callback function and passes the object to it. The objLogger function prints the property name and it's value.  

var objLogger = function(obj){
  for (var item in obj){
  if(obj.hasOwnProperty(item)){
     console.log(item + ': ' + obj[item]);
    }
  }
}

var changeName = function(obj, callback){
  obj.name = 'abhi2';
  callback(obj);           //callback function execution
}

var obj1 = {name: 'abhi'};
changeName(obj1, objLogger);       //name: abhi2

Another good practice when using callbacks is to check their type before executing them.

if( typeof callback === 'function'){
    callback(obj); 
}


Synchronous & Asynchronous Callbacks

The setTimeout examples that we saw earlier were callbacks which are executed asynchronously. The logger function that we just saw was executed synchronously. So we can use them in both ways in similar way.
The callbacks are used more often in the asynchronous context (for example, Node.js). However, please note, just by using callbacks our code doesn't automatically become asynchronous. If we are writing our own callbacks, we can use them either synchronously or asynchronously.

Callback Hell Problem

When we write a lot of nested callbacks the code looks unwieldy and difficult to understand. This problem of nested callbacks is known as callback hell problem.

Suppose, we have an example where we load a book first, then we load it's chapters and then we load pages and so on... We want to do that asynchronously and on success of previous one, the next call goes out. The code may look something like this:

var connection = new connection();
connection.loadBook(function(err, connection) {
    connection.loadChapter(function(err, connection) {
        connection.loadPages(err, function(err, collection) {
        });
    });
}); 

As you can see the code has started looking bad with multiple nested callbacks. In case of complex code, this might go several layers. Such a code is not only difficult to read but also to debug.
One way to combat this is to always use named functions instead of anonymous functions. That will make it somewhat easier to read. I will be discussing more on how to combat this callback hell problem in my next week's blog post.

Conclusion

Callbacks are used very commonly in JavaScript code. A proper understanding of these helps us write better code and understand the pre-written code better. These are used extensively in various JavaScript libraries and frameworks.



No comments:

Post a Comment