Callbacks in JavaScript
You are at the right blog to understand Callbacks.

Callbacks? The very first time you heard about this, it seems something too heavy to tackle.
But not now! I will make it sure to take you from beginner to advanced understanding of closures. No confusion, no heavy jargon. Just simple logic.
Functions in JavaScript holds no "special" place
Alright then, before stepping into callbacks, let's understand what functions in Js are? In JavaScript, functions are just values. They are similar to: numbers, strings, arrays.
Functions can be assigned as values to variables, passed as arguments, returned or invoked from another function.
Have a look at this:
function greet(){
console.log("Hello callback");
}
const greetUser = greet;
greetUser(); //Hello callback
In the above code snippet, we didn't call greet() directly. Instead it is initially stored into a variable and invoked it later.
That's how functions are treated as values.
Coming to Callback
Definition: A Callback is simply a function passed as an argument to another function, to be executed later.
A real-world analogy:
You order food ( a callback) at restaurant
Restaurant ( receiver function) calls us when order is ready
Once food is ready, they deliver your order.
So, the receiver function calls it when something happens.
Check this out:
function greet(name) {
console.log("Hello" + name);
}
function processUser(callback) {
callback("Atharv") //equivalent to greet("Atharv")
}
processUser(greet); //Hello Atharv
Visualize it carefully. We created two independent functions greet() and processUser(), but passed greet () as an argument to processUser( ).
Code explanation:
Function greet with parameter name is created.
Function processUser with parameter callback is created.
When
processUser(greet)is called, the greet being the argument of processUser is equivalent to its callback parameter.[callback = greet]So, eventually
callback("Atharv") = greet("Atharv"). Nowgreet()holdsnameparameter so it becomesname = "Atharv".So callback("Atharv") executes, which prints out Hello Atharv.
Reason behind existence of Callbacks
Here comes the actual question - Why do Js need callbacks?
The answer is quite simple - Because of asynchronous behavior of Js.
JavaScript is synchronous and single-threaded, so long-running operations cannot block the entire program. To handle operations that take time (such as timers, network requests, or write/read files), JavaScript uses asynchronous mechanisms - Callback provide a way to specify what code should execute when those operations complete.
Let's visualize with a real problem
Imagine this:
console.log("Start");
setTimeout(function (){
console.log("Data received");
},2000);
console.log("End");
Output:
Start
End
Data received
When JavaScript executes this program; the data is delivered after 2 seconds. Now the problem is what to execute after data is ready? We use a callback.
How Callback solves this problem
This is also one of those examples where callback accepts parameters from the calling function.
function fetchData(callback){
setTimeout(function (){
const data = "JavaScript";
callback(data);
}, 2000);
}
function displayData(result){
console.log(result);
}
fetchData(displayData);
Here is the execution flow: When fetchData(displayData) is invoked, the fetchData starts async behavior for 2 seconds until data is received and then it calls the callback. This ensures that the code executes without delay.
Short but sweet mental model
Callback says, "Run this function AFTER something is done."
Use cases of Callbacks
Callback shines whenever dealing with asynchronous code (setTimeout, react to events, API calls etc). They also work array methods (map, filter, forEach).
1. setTimeout
Syntax: setTimeout(callback fn, delay);
setTimeout( function () {
console.log("Execute after timer ends");
}, 2000);
2. Event-Listeners
Syntax: element.addEventListener(event, callbackFunction);
element → HTML element you want to listen to.
event → Event name (
"click","mouseover","keydown", etc.).callback Function → Function that runs when the event occurs.
button.addEventListener("click", () => {
console.log("Clicked!");
});
3. Array Methods
function fetchData(callback) {
const data = ["React", "JavaScript", "Node"];
data.forEach(function (item) {
callback(item);
});
}
fetchData(function (result) {
console.log(result);
});
Wait! Is this looking too complex? Yes, this one needs an explanation.
Look carefully - The execution flow is:
fetchData(fn (result) {----})is called - The anonymous function is passed as the argument.So inside
fetchData: callback = function (result) { console.log(result); }Array is created
const data = ["React", "JavaScript", "Node"];
forEach()starts iterating
First iteration:
item = "React"
Then:
callback(item) becomes callback("React");
which executes:
function (result) {
console.log(result); //React (item = React)
}
The same process repeats for "JavaScript" and "Node". This example represents that callback is not restricted to single value. The same callback can be invoked multiple times, each time with different data.
Pitfalls of callback
Callback often solves blocking behavior of JavaScript and async problems, but they can introduce nesting issues.
Callback Hell
Nesting multiple callbacks creates callback hell.
Imagine this:
Suppose you want to:
Get a user.
Get that user's posts.
Get comments on a post.
getUser(function(user) {
console.log("User:", user);
getPosts(user.id, function(posts) {
console.log("Posts:", posts);
getComments(posts[0].id, function(comments) {
console.log("Comments:", comments);
});
});
});
Each task waits for the previous one to finish.
And this creates a problem-
Why nesting callbacks is an issue?
Poor Readability- as we keep nesting it the more difficult it becomes.Hard Error Handling- Debugging errors is challenging.Hard to maintain
Nesting multiple asynchronous operations = Losing track of logic!
Let's get out of this HELL
Callbacks solved async issues but ended up creating readability problems.
To get rid of this JavaScript got something new for you - Introducing Promises and Async/Await.
Yes, promises, async/await solves the problem of readability by making the flow of logic smoother. But callbacks are still important, because async Js is built on top of callbacks.
And To Be Honest, once callbacks hit your mind, understanding Promises & Async/Await becomes easier.
Conclusion
Callbacks might feel a bit confusing initially, but once you understand this - They are simply functions passed as arguments and executed later when a task is completed. You might get more confident about Callbacks.
Key points to carry
Callback is function passed to another function.
Help execute code later
Helps handle asynchronous operations without blocking execution.
Ensures about running the code at right time.
Used with variety of cases (timer, networks, events, APIs)
Nesting callbacks = Callback Hell -> use Promises and Async/Await to break the hell.


