Callback Function in JavaScript: What It Is & How It Works

Introduction

A callback function is a function that is executed after successfully executing the first or previous function. Moreover, it won’t start operation unless the previous function is successfully executed. This function is passed as an argument within the first or previous function, as the first function successfully executes the whole operation. Then, the callback (the function passed as an argument) starts its operation.

This real-life example will help you better understand callbacks:

You are calling your friend, who is already on another call with his friend. In this case, your friend will say, “I will call you back” after this call.

As you can realize through this example, a callback function won’t execute as long as the previous or first function is not completing its operation.

You might be confused about why we should use a callback function, so you don’t need to worry about that. We will explore everything in detail, from why we should use it to how it works, and much more.

Why Use Callbacks in JavaScript?

As we know, JavaScript is an event-driven programming language, which means it needs a trigger to execute a block of code or function that explicitly points to callback functions. Here, the trigger or event is the first function, while the function or block of code that will be executed is the callback function.

For this reason, these functions are very useful in JavaScript. JavaScript is full of callback functions—you just need to think a bit critically to spot them. These functions are very useful for enabling functionality and working with APIs, as we often need to stop executing specific functionality while the data is being fetched from the APIs. Let’s try to explore this by putting it under the microscope.

Event-Handler: Although callbacks aren’t typically known for this property, I am going to put this as the first point so that you can understand it clearly. An event handler is a trigger (like a click, mouse move, etc.). When the trigger occurs, it executes a callback function. For instance, if we click on any product on an e-commerce website, it shows a popup with full information about the specific product we clicked on. In this case, the trigger (click) is the first function, while the popup is the callback function that executes for the trigger (click).

Asynchronous: These functions are often used in asynchronous programming to ensure that certain code runs after completing an operation, such as an internet request. We commonly work with APIs when fetching data from the internet. After making a request, we use a callback function to initiate a specific operation once the request is complete. Since fetching data can take some time, the callback function allows us to start processing the data immediately after the request is finished.

Moreover, this example will help you understand why you should use a callback function:

JavaScript

copy

function firstFunction() {
  console.log('I must print before printing the secondFunction');
}

function secondFunction() {
  console.log('I must print after printing the firstFunction');
}

firstFunction();
secondFunction();

/* output:
I must print before printing the secondFunction
I must print after printing the firstFunction */

As you can see in the example above, we wrote two functions: the first function's name is firstFunction and the second is secondFunction. We want to print firstFunction before printing secondFunction. The reason is that secondFunction shouldn’t be executed before firstFunction. The result is correct as expected because there is no possible barrier in firstFunction that would prevent it from completing its operation; that is why firstFunction is printed first before secondFunction.

Now in our next example, we will analyze whether secondFunction will wait for firstFunction since we will add a barrier manually so that firstFunction takes some time. We’ll check whether we can delay the execution of secondFunction until firstFunction is fully executed. Can we achieve this without using the callback function? This example will help you understand how callback functions work.

JavaScript

copy

function firstFunction() {
  setTimeout(() => {
    console.log('I must print before printing the secondFunction');
  }, 2000)
}

function secondFunction() {
  console.log('I must print after printing the firstFunction');
}

firstFunction();
secondFunction();

/* output:
I must print after printing the firstFunction
I must print before printing the secondFunction */

Did you see in the example above that the secondFunction didn’t wait for firstFunction, and it was executed before executing the firstFunction? Now the result is not expected as we expected because we added a barrier manually by using a setTimeout() function.

setTimeout() is a JavaScript function that takes a callback function and a time interval as arguments. It does not execute the callback until the specified time has elapsed. Once the time is complete, the function executes the callback.

Now, it is expected that you will understand why we should use callback, so we are moving one step further.

Callback function with Examples

Now we have enough understanding of the callback function, we will try to learn this by writing the codes in JavaScript:

Simple Callback Function

JavaScript

copy

function firstFunction(callback) {
  console.log('I am on another call, I will call you back after ending this call.');
  callback();
}

function secondFunction() {
  console.log('Hi, I am finished with this call.');
}

firstFunction(secondFunction)
/* output:
I am on another call, I will call you back after ending this call.
Hi, I am finished with this call. */

Did you notice the example above? We wrote two functions: firstFunction and secondFunction. Within our firstFunction, we passed secondFunction as a parameter and invoked secondFunction within firstFunction. This is mandatory; now it has become a callback function. The output is correct, but it is tricky to identify the callback function. You will explicitly see the callback function's job in the next example. For now, we need to define the steps of a callback function.

Must pass the parameter of the callback function

We need to pass the parameter of our callback function within our first function, as we did in our example above: firstFunction(callback)

You can give any name to the parameter while passing the callback function, as we used ‘callback’ in our example above. However, you can use whatever name you want, as is usual in normal functions.

Must invoke the parameter of the callback function

Make sure to invoke the parameter within the first function as we invoke any function, like this: callback(), that is being used in our first function. As you can see in this example above, we did the same.

JavaScript

copy

function firstFunction(callback) {
  console.log('I am on another call, I will call you back after ending this call.');
  callback();
}

Check our firstFunction where we passed callback as a parameter, and we also invoked it at the end of the firstFunction by the same name callback, but with parentheses, as it is a function: callback().

Must pass an argument as a function in our first function while calling

Finally, we need to make sure to pass an argument in our first function, as it uses a parameter and requires an argument for execution, like this: firstFunction(secondFunction). We need to pass the name of our callback function that will be invoked after the successful execution of the first or preceding function. As you can see, we did the same in our example:

JavaScript

copy

firstFunction(secondFunction)

Make sure not to add parentheses while calling the functions.

This is wrong: firstFunction(secondFunction())

This is correct: firstFunction(secondFunction)

Asynchronous callback

JavaScript

copy

function firstFunction(callback) {
  setTimeout(() => {
    console.log('I am on another call, I will call you back after ending this call.');
    callback();
  },3000);
}

function secondFunction() {
  console.log('Hi, I am finished with this call.');
}

firstFunction(secondFunction)

/* output:
I am on another call, I will call you back after ending this call.
Hi, I am finished with this call. */

Did you notice in this example that we forcibly stop the execution of our firstFunction for 3 seconds to check whether our secondFunction will wait as intended? In this case, the secondFunction does wait for firstFunction, which illustrates the real job of a callback function. Hopefully, you will understand the whole concept of callback functions more clearly now.