Callbacks in JavaScript: Why They Exist
A simple guide to understanding how functions talk to each other.

Full-stack developer and startup founder building tech solutions in Ayodhya. Vlogger with 27k+ followers sharing my journey in technology and SaaS.
When you first learn JavaScript, functions seem pretty simple. You write a block of code, give it a name, and call it when you need it to do something.
But as you spend more time with JavaScript, you will start seeing functions being passed around like variables. This can look really confusing at first! Today, we are going to break down what a callback function is, why we need them, and how they help keep our websites running smoothly.
Functions are Just Values
Before we talk about callbacks, there is one secret you need to know about JavaScript: Functions can be treated just like normal values.
Just like you can pass a string or a number into a function, you can also pass another function into a function.
// A normal variable
const myName = "John";
// A function stored in a variable
const sayHello = function() {
console.log("Hello!");
};
Because sayHello is just a value, we can hand it over to other parts of our code.
What is a Callback Function?
A callback function is simply a function that you pass into another function as an argument. The receiving function holds onto your callback and promises to "call it back" (run it) at a later time.
Here is a very simple example of passing a function as an argument:
// 1. This is our callback function
function waveGoodbye() {
console.log("Goodbye, see you later!");
}
// 2. This function takes another function as a parameter
function endMeeting(callback) {
console.log("The meeting is now over.");
callback(); // We run the callback function here!
}
// 3. We pass 'waveGoodbye' into 'endMeeting'
endMeeting(waveGoodbye);
Output:
The meeting is now over.
Goodbye, see you later!
Diagram: Function Calling Flow
[ endMeeting Function ] starts running
|
v (does its own work)
Prints "The meeting is now over."
|
v (runs the callback you gave it)
[ waveGoodbye Function ] starts running
|
v
Prints "Goodbye, see you later!"
Why Do We Need Callbacks? (Asynchronous Programming)
Passing functions around is neat, but why do we do it?
Most of the time, JavaScript runs top-to-bottom, one line at a time. But some tasks take a long time to finish, like downloading a picture from the internet. If JavaScript stopped and waited for the picture to download, your entire website would freeze!
To fix this, JavaScript uses asynchronous programming. This means it can start a long task, move on to other things, and finish the long task later.
This is where callbacks save the day.
Think of it like ordering food at a busy restaurant. You don't stand at the counter and wait (freezing the line). Instead, you give the cashier your name (the callback). You go sit down and talk to your friends. When your food is ready, the cashier calls your name!
Common Scenarios for Callbacks
You will use callbacks all the time in everyday web development. Here are two very common examples:
1. Waiting for a timer (setTimeout) You tell JavaScript to wait 3 seconds, and then run your callback function.
setTimeout(function() {
console.log("3 seconds have passed!");
}, 3000);
2. Waiting for a user to click a button You give the button a callback function. The button holds onto it and only runs it when the user actually clicks.
const myButton = document.getElementById("clickMe");
myButton.addEventListener("click", function() {
console.log("The button was clicked!");
});
The Problem: Callback Nesting
Callbacks are incredibly useful, but they have a dark side.
What if you have to do a bunch of things in a specific order, and every step takes time? You have to put a callback inside a callback inside a callback.
Let's say we are making a burger:
Get the bun.
Cook the meat.
Add the cheese.
If we use callbacks for all of this, the code starts to look like a sideways pyramid:
getBun(function(bun) {
cookMeat(bun, function(meat) {
addCheese(meat, function(burger) {
console.log("The burger is finally ready!");
});
});
});
Diagram: Nested Callback Flow
Step 1 Starts...
\
Step 1 Finishes -> Step 2 Starts...
\
Step 2 Finishes -> Step 3 Starts...
\
Step 3 Finishes!
This messy, triangle-shaped code is famously called "Callback Hell" or the "Pyramid of Doom." It is very hard to read and even harder to fix if something breaks.
(Note: Modern JavaScript has new tools like Promises and Async/Await to fix this exact problem, which we will cover in a future post!)
Conclusion
Callback functions might seem weird at first, but they are just JavaScript's way of being polite. They allow functions to hand off instructions to each other so your website never has to freeze while waiting for things to finish.




