Understanding JS Callback Functions

Note: This post is work-in-progress learning-note and still in active development and updated regularly.

In Mozilla Development Network (MDN) callback function is defined as ‘a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action’. In JS callback functions are important concept and these functions are popular in many JavaScript libraries including JQuery.

Brandon Morelli in a post in Medium explains JS callback function in simple English as: callback functions are functions to be executed after another function function execution. Because JS is very event driven language, it does not wait to run a block of code before moving on to the next function execution. For example, if we wanted to wait execution of certain function (eg. user input) before moving on to the next function, callback functions come very handy. In such situation we could use setTimeout callback function to delay execution.

Tip: JS Callbacks are a way to make sure certain code doesn’t execute until other code has already finished execution – Brandon Morelli.

Callback functions could be synchronous (executes immediately) or asynchronous (executes after an event). For example, we want to perform some routine tasks like perform some operation or display content after some clicking a button, or fetching data from internet.

To better understand the callback function concept, I am using following examples:

1. Example One: from MDN Callback Function
//initialize function name
function greeting(name) { // (*) initialize
  console.log('Hello ' + name);
}

//define callback function
function processUserInput(callback) {
  let name = prompt('Please enter your name.'); //user input "Robert" 
  callback(name);
}

//Invoke function
processUserInput(greeting); // (**) call back function

//OUTPUT
Hello Robert

In the example above, we initialize a basic function named greeting with one parameter variable name. In the code block, we print value of name variable with "Hello" string.

In the next function processUserInput with a single parameter variable callback,  we assign the var name (from function top) to the value received from user input to built-in prompt() function. At this stage, the function execution waits until user inputs name in the browser console. Now we will assign the value of name variable as callback()function argument as callback(name).

When the processUserInput(greeting); is invoked with greeting(name) callback function, we receive 'Hello Robert' output. The processUserInput(greeting); line in (**) is equivalent to the following:

//invoke function
processUserInput(greeting):

//it is equivalent to the following
processUserInput(function greeting(name) {
  console.log('Hello ' + name);
});

Actually in this case we are simply calling greeting(name) function shown in (*).

2. Example 2: from Callbacks, Promises, and Async  by Chris Nwamba (scotch.io)
//initialize function greeting
function greeting(name) { // (1) function with parameter
  console.log(`Hello ${name}, you are welcome!`);
}

//initialize callback function
//(2) three parameter
  let fullName = `${firstName} ${lastName}`;
function introduction(firstName, lastName, callback) {  

  callback(fullName);
}
//invoke callback function greeting
// (3) note braces are not used after greeting
introduction('Robert','Smith', greeting); 

//OUPUT
Hello Robert Smith, you are welcome!

In the example above by Chris, a function named greeting is declared (1) with one parameter var name. In second step (2) a callback function name introduction is defined with three parameters of fistName, lastName, callback. In body of the callback function, the fistName & lastName variable is assigned to a new variable fullName which is then passed to as argument of callback function as callback(fullName).

In step (3), when callback function is invoked, please note that ( ) after function greeting are not used because it is passed here as argument and not as function.

Tip: The callback function is not run unless called by its containing function, it is called back. Hence, the term call back function

3. Example 3: Function expressions and arrowsThe Modern JavaScript Tutorials
//Initialize function ask
function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

//Initialize callback function for input Yes
function showOk() {
  console.log( "You agreed." );
}

//Initialize callback function for No
function showCancel() {
 console.log( "You canceled the execution." );
}

// usage: functions showOk, showCancel are passed as arguments to ask
ask("Do you agree?", showOk, showCancel);

In the example above, a simple function ask is created with three parameters (question, yes, no). The function ask question in the form a built-in window function conform() which outputs a boolean value indicating whether OK or Cancel was selected (true means OK).

Then we initialize two callback functions showOK() and showCancel() with corresponding output messages, respectively  for OK or Cancel in the browser console. The idea is that these functions can be passed and expected to be “called back” function later if necessary.

In the example above, showOk becomes the callback for the “yes” answer, and showCancel for the “no” answer.

Note: Callback functions are useful component of JavaScript. More advanced callback features including synchronous & asynchronous functions is discussed by Zell Liew in more detail.

Wrapping Up

JavaScript callback functions are important component of JS programming and used extensively in many libraries and framework. The are commonly used in either in simple functions like setInterval, event listening or when making API calls. This is often confusing even to many experienced JS developers.

Resources & Further Reading:

While preparing this post, I have referred the following references extensively. Please to refer original posts for more detailed information.