What is a Callback Function?
A callback function is simply a function that is passed as an argument to another function
Example:
function operation(a,b,cb){
console.log(cb(a,b))
}
const sum = (a,b) => a+b
const difference = (a,b) => a-b
const multiplication = (a,b) => a*b
const division = (a,b) => a/b
operation(10,5, sum) // 15
operation(10,5, difference) // 5
operation(10,5, multiplication) // 50
operation(10,5, division) // 2
Why Callbacks Exist?
JavaScript is single-threaded, meaning it can execute only one task at a time.
But real-world applications need to:
Fetch data from APIs
Read files
Handle user interactions
Wait for timers
If JavaScript waited for each task to complete synchronously, the application would freeze.
const data = fetchDataFromServer(); // takes 5 seconds
console.log(data);
This would block everything for 5 seconds. Thus our application will less responsive. To fix this we use callbacks.
Solution: Asynchronous Execution with Callbacks
function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 2000);
}
fetchData((data) => {
console.log(data);
});
👉 Instead of blocking:
The task runs in the background
Callback executes after completion
Callbacks in Asynchronous Programming
Example: setTimeout
setTimeout(() => {
console.log("Executed after 2 seconds");
}, 2000);
Example: API Simulation
function getUser(callback) {
setTimeout(() => {
callback({ username: "krish", email: "krish@example.com" });
}, 1000);
}
getUser((user) => {
console.log(user);
});
The callback ensures code runs only when data is ready.
Common Use Cases of Callbacks
1. Event Handling
document.getElementById("btn").addEventListener("click", () =>{
console.log("Button clicked!");
});
2. File System (Node.js)
import fs from "fs";
fs.readFile("file.txt", "utf-8", (err, data) => {
if (err) throw err;
console.log(data);
});
3. API Calls (Before Promises)
function fetchData(callback) {
setTimeout(() => {
callback("API response");
}, 1000);
}
4. Array Methods
const numbers = [1, 2, 3];
numbers.forEach((num) => {
console.log(num);
});
Basic problem of callback nesting
Callbacks work well… until they start nesting deeply.
Example:
getUser((user) => {
getOrders(user.id, (orders) => {
getOrderDetails(orders[0], (details) => {
console.log(details);
});
});
});
Problems:
Hard to read
Difficult to debug
Error handling becomes messy
Code becomes pyramid-shaped
Solutions:
Start using promises
Try using async await
These are built on top of callbacks, not replacements at the core level.

