Skip to main content

Command Palette

Search for a command to run...

Callbacks in JavaScript: Why They Exist

Published
4 min read
Callbacks in JavaScript: Why They Exist

In this article we'll explore the concept of callbacks in JavaScript along with simple code examples that will help us understand it more easily.

A callback function is a function that is passed into another function as an argument and then executed later inside that function. In JavaScript, functions are treated like normal values. This means we can store them in variables, pass them to other functions, and even return them from functions. Because of this feature, one function can receive another function and decide when to execute it. The function that gets passed is called a callback function.

function greet(name, callback) {
  console.log("Hello " + name);
  callback();
}

function sayBye() {
  console.log("Bye!");
}

greet("Sam", sayBye);

In this example, sayBye is passed into the greet function and executed inside it. Since it is called back by another function, it is known as a callback.

Why Callbacks Are Used in Asynchronous Programming

Callbacks are heavily used in asynchronous programming. JavaScript runs on a single thread, which means it can only perform one operation at a time. However, many tasks in web development take time, such as fetching data from an API, reading files, or waiting for timers.

If JavaScript waited for each of these tasks to finish before moving forward, the application would freeze. Instead, JavaScript starts the task and continues executing other code. Once the task finishes, a callback function is executed. This allows the program to remain responsive.

A simple example is using setTimeout.

console.log("Start");

setTimeout(function () {
  console.log("Timer finished");
}, 2000);

console.log("End");

The function passed to setTimeout is the callback. JavaScript schedules it to run after 2 seconds while continuing to execute the rest of the code. That is why the output becomes:

Start
End
Timer finished

Passing Functions as Arguments

One powerful concept in JavaScript is that functions can be passed as arguments. Since functions are values, they can be sent into other functions to control how those functions behave.

function processNumber(num, operation) {
  operation(num);
}

function double(n) {
  console.log(n * 2);
}

function square(n) {
  console.log(n * n);
}

processNumber(5, double);
processNumber(5, square);

In this example, the processNumber function remains the same, but its behavior changes depending on the callback that is passed. This makes code more flexible and reusable.

Callback Usage in Common Scenarios

Callbacks appear in many real-world JavaScript situations. One of the most common examples is event handling. When a user clicks a button, types in an input field, or scrolls a page, a callback function runs in response to that event.

button.addEventListener("click", function () {
  console.log("Button clicked");
});

The function passed to addEventListener is a callback that runs whenever the click event happens.

Callbacks are also used in:

  • Timers like setTimeout and setInterval

  • API requests

  • File operations in Node.js

  • Handling user interactions in the browser

Because asynchronous tasks are everywhere in web development, callbacks became a fundamental part of JavaScript programming.

Basic Problem of Callback Nesting

Although callbacks are useful, they can sometimes lead to messy code when multiple asynchronous operations depend on each other. This situation is known as callback nesting, often referred to as callback hell.

loginUser(function () {
  getUserProfile(function () {
    getPosts(function () {
      console.log("All data loaded");
    });
  });
});

Here each step waits for the previous one to complete, which forces the code into deeper levels of nesting. As the number of operations increases, the code becomes harder to read, maintain, and debug.

Because of this problem, modern JavaScript introduced Promises and later async/await, which allow developers to handle asynchronous operations in a cleaner and more structured way.

And saved our eyes and brain!