Skip to main content

Command Palette

Search for a command to run...

JavaScript Callback Functions Explained Simply (With Real Examples & Callback Hell)

Published
5 min read
JavaScript Callback Functions Explained Simply (With Real Examples & Callback Hell)

So… what exactly is a callback function?

Well technically!!!…

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

Hmm… sounds like MDN uncle again entered the chat 😅

Let’s understand this in our own way.


Functions as Values (Yes, Functions are VIPs 👑)

In JavaScript, functions are not just… functions.

They are values.

Just like numbers, strings… even like your favourite song.

function sayHello() {
  console.log("Hello Bhai");
}

const greet = sayHello;

greet(); // Hello Bhai

See what happened?

We didn’t call sayHello, we stored it.

That means:

👉 Function = Value 👉 Value = Can be passed around

Now things start getting interesting…


Passing Function as Argument (Entry of Callback 🚪)

Let’s say your mom tells you:

"Go to the market… and after that call me"

Here “call me” is something you do after work is done.

That is exactly what callback is.

function doTask(taskName, callback) {
  console.log(`Doing task: ${taskName}`);
  callback();
}

function taskFinished() {
  console.log("Task completed. Reporting back 😎");
}

doTask("Buy Vegetables", taskFinished);

Output:

Doing task: Buy Vegetables
Task completed. Reporting back 😎

So here:

👉 taskFinished is a callback 👉 It is passed into doTask 👉 It is executed later


Visual Flow (How Callback Works 🧠)

Think like this:

doTask()
   ↓
Work happens
   ↓
Callback gets called

Simple life. No tension.


Now Real Problem Begins… Asynchronous World 🌍

Till now everything was simple.

But JavaScript is not simple…

It loves drama.


Example: Ordering Food 🍔

function orderFood(callback) {
  console.log("Order placed...");

  setTimeout(() => {
    console.log("Food delivered 🍕");
    callback();
  }, 2000);
}

function eatFood() {
  console.log("Eating food... happiness restored 😌");
}

orderFood(eatFood);

Output:

Order placed...
(wait 2 seconds)
Food delivered 🍕
Eating food... happiness restored 😌

Why callback here?

Because:

👉 Food delivery takes time 👉 We don’t want to block everything 👉 So we say: “When done… call this function”

This is asynchronous programming.


Why Callbacks Are Used?

Let’s make it crystal clear:

1. Handle delayed operations

Like:

  • API calls

  • File reading

  • Database queries

2. Avoid blocking code

JavaScript is single-threaded.

If one thing blocks → everything blocks.

Callbacks help avoid that mess.


Common Real-Life Callback Scenarios

1. Button Click (Frontend)

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

👉 User clicks → callback runs


2. API Call

fetchData(function (data) {
  console.log("Data received:", data);
});

👉 When data comes → callback runs


3. Timer

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

👉 Time finishes → callback runs


Now Comes The Villain 😈

Callback Hell (Nested Callbacks)

Everything was fine…

Until this happened:

loginUser(function () {
  getUserData(function () {
    getPosts(function () {
      displayPosts(function () {
        console.log("All done 😵");
      });
    });
  });
});

Look at this 😭

This is called:

👉 Callback Hell 👉 Pyramid of Doom 👉 “Why did I choose programming?” moment


Visual Representation of Callback Hell

loginUser
   ↓
 getUserData
   ↓
  getPosts
     ↓
   displayPosts
       ↓
     Done 😵

Indentation increasing = Happiness decreasing


What’s the Problem Here?

  1. Hard to read

  2. Hard to debug

  3. Hard to maintain

  4. One error → everything breaks

Basically:

👉 Code becomes spaghetti 🍝


Conceptual Understanding (Important ⚠️)

Callbacks are not bad.

Overusing nested callbacks is bad.

Just like:

  • Sugar is fine

  • Too much sugar → diabetes 😅


So What’s The Solution?

Modern JavaScript said:

“Enough is enough…”

And gave us:

👉 Promises 👉 Async/Await

(But that’s another blog… patience rakho 😏)


Final Summary (Revision Time 📚)

  • Function can be treated as value

  • Function can be passed as argument

  • That passed function = Callback

  • Callbacks are used in async operations

  • Too many nested callbacks = Callback Hell


Real Talk Ending 😌

Callbacks are like instructions you leave for future.

“Bhai… jab kaam ho jaye… mujhe bata dena”

Simple.

But if you keep stacking instructions inside instructions inside instructions…

Even your brain will say:

“Main nahi kar raha… tu khud dekh le” 😭


Homework… Because I Care 😏

Try this:

  1. Create a function downloadFile(callback)

  2. Simulate delay using setTimeout

  3. After download → call callback

  4. Inside callback → print "File Ready"

Bonus:

Try creating nested callbacks and see where life starts hurting.


And yes…

If you understood this…

You are officially one step closer to escaping callback hell 😎