Skip to main content

Command Palette

Search for a command to run...

Callbacks in JavaScript: Why They Exist

Updated
3 min readView as Markdown
Callbacks in JavaScript: Why They Exist

1. The Foundation: Functions are First-Class Citizens

Before diving into callbacks, you must understand that in JavaScript, functions are values. Just like you can pass a string or a number into a function, you can pass a function into another function.

Concept: A function passed as an argument to another function is called a Callback Function.

Example (Simple Callback)

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

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

greet("John", sayBye);

Output:

Hello John
Goodbye!

2. Why do they exist? (The "Why")

JavaScript is single-threaded, meaning it can only do one thing at a time. If we have a task that takes 5 seconds (like fetching data from an API), we don't want the whole website to freeze.

Callbacks allow us to say: "Hey, go do this long task, and when you're finished, run this specific function." This is the heart of Asynchronous Programming.

3. Synchronous vs. Asynchronous Callbacks

It's easier to learn callbacks in two stages:

A. Synchronous (Simple Example)

The callback is executed immediately.

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

greet("Diwya", () => {
    console.log("The callback was executed!");
});

B. Asynchronous (Real-world Example)

Commonly seen in timers or data fetching.

console.log("Ordering pizza...");

setTimeout(() => {
    console.log("Pizza is here! (This is the callback)");
}, 3000);

console.log("Watching TV while waiting...");

Passing Functions as Arguments

Callbacks work because functions can be passed like values.

Example

function processUserInput(callback) {
  const name = "Alice";
  callback(name);
}

processUserInput(function(name) {
  console.log("User name is: " + name);
});

4.Common Use Cases of Callbacks

Timers

setTimeout(() => {
  console.log("Executed later");
}, 1000);

Event Handling

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

API Calls (Old Way)

fetchData(function(response) {
  console.log(response);
});

5. The Dark Side: Callback Hell

When you need to do multiple asynchronous tasks in a specific order (e.g., Login -> Get User Profile -> Get User Posts), you end up nesting callbacks inside callbacks.

The Result: A "Pyramid of Doom" that is nearly impossible to read or debug.

Example of the problem:

getData(function(a) {
    getMoreData(a, function(b) {
        getEvenMoreData(b, function(c) {
            console.log(c);
        });
    });
});

Note: This is exactly why Promises and Async/Await were invented later!

Conceptual Problem Explanation

  • Each async step depends on the previous one

  • So callbacks get nested

  • Code becomes deeply indented

👉 Result:

  • Poor readability

  • Hard maintenance

Modern Solution (Quick Mention)

To fix callback problems:

  • Promises

  • Async/Await

async function fetchData() {
  const data = await getData();
  console.log(data);
}

JavaScript form basic concepts to Advance

Part 4 of 17

Master JavaScript from the ground up. This series takes you on a complete journey from fundamental syntax and variables to advanced asynchronous patterns, closures, and performance optimization. Whether you are a beginner writing your first line of code or an intermediate developer looking to bridge the gap to seniority, these guides provide deep dives, practical examples, and modern best practices for the 2026 ecosystem.

Up next

The new Keyword in JavaScript

1. What the new Keyword Actually Does In JavaScript, the new keyword is used to create an instance of a user-defined object type or one of the built-in object types that has a constructor function. Th