Skip to main content

Command Palette

Search for a command to run...

Async Made Simple: Understanding JavaScript Callbacks

Updated
β€’3 min readβ€’View as Markdown

πŸ“ž Understanding Callback Functions in JavaScript (Beginner to Intermediate)

JavaScript is powerful because functions are first-class citizens. That means you can treat them like values β€” pass them around, store them, and execute them dynamically.

One of the most important concepts built on this idea is the callback function.

🧠 What is a Callback Function?

A callback function is simply a function that is passed as an argument to another function and is executed later.

πŸ‘‰ Basic Example

function greet(name) {
  console.log(`Hello, ${name}`);
}

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

processUserInput(greet);

πŸ’‘ What’s happening?

. greet is passed as an argument

. processUserInput calls it later

. So, greet becomes a callback

πŸ”„ Functions as Values (Core Idea)

Before callbacks make sense, you need to understand this:

function sayHi() {
  console.log("Hi!");
}

const fn = sayHi; // function assigned to variable
fn(); // works!

You can also pass functions:

function execute(fn) {
  fn();
}

execute(sayHi);

πŸ‘‰ This ability is what enables callbacks.

⚑ Why Callbacks are Used (Especially in Async Code)

JavaScript is non-blocking. It doesn’t wait for slow operations like:

. API calls

. File reading

. Timers

Instead, it uses callbacks to handle results later.

⏱️ Example:

console.log("Start");

setTimeout(() => {
  console.log("This runs after 2 seconds");
}, 2000);

console.log("End");

🧾 Output:

Start

End

This runs after 2 seconds

πŸ‘‰ The function inside setTimeout is a callback

πŸ”§ Passing Functions as Arguments

Callbacks are everywhere in JavaScript:

function calculate(a, b, operation) {
  return operation(a, b);
}

function add(x, y) {
  return x + y;
}

function multiply(x, y) {
  return x * y;
}

console.log(calculate(2, 3, add));       // 5
console.log(calculate(2, 3, multiply));  // 6

πŸ‘‰ This makes your code flexible and reusable.

🌍 Real-World Callback Usage

  1. Event Handling

    document.getElementById("btn").addEventListener("click", () => {
      console.log("Button clicked!");
    });
    

    πŸ‘‰ The function runs only when the event happens.

  2. API Calls (Classic Style)

    function fetchData(callback) {
      setTimeout(() => {
        const data = { user: "Vaibhav" };
        callback(data);
      }, 1000);
    }
    
    fetchData((data) => {
      console.log(data);
    });
    

⚠️ The Problem: Callback Nesting (Callback Hell)

When callbacks are nested inside callbacks, code becomes messy and hard to manage.

😡 Example

setTimeout(() => {
  console.log("Step 1");

  setTimeout(() => {
    console.log("Step 2");

    setTimeout(() => {
      console.log("Step 3");
    }, 1000);

  }, 1000);

}, 1000);

πŸ‘‰ This pyramid structure is called Callback Hell

❌ Why Callback Hell is Bad

Hard to read 😡

Hard to debug πŸ›

Hard to maintain πŸ”§

🧩 Conceptual Fix (Preview)

To solve this, modern JavaScript uses:

. Promises

. async/await

But callbacks are still the foundation, so understanding them is crucial.

πŸ“Š Diagram: Function Calling Flow

main()
  └── processUserInput(callback)
        └── callback(name)

πŸ“Š Diagram: Nested Callback Flow

Step 1
  └── Step 2
        └── Step 3

(Each step waits for the previous one)

🧠 Key Takeaways

A callback is a function passed into another function.

JavaScript uses callbacks heavily for async behavior.

They enable flexibility and reuse.

But excessive nesting leads to callback hell .

πŸš€ Final Thought

Callbacks are simple in concept but powerful in practice. Once you master them, concepts like Promises and async/await will feel much easier.

1 views

More from this blog