Skip to main content

Command Palette

Search for a command to run...

Callbacks in JavaScript: Why They Exist ?

Updated
•4 min read•View as Markdown

What are Functions in JavaScript

Think of a function as a reusable block of code that can perform a specific task and can be used multiple times by the user. We use them to avoid repeating code, making programs cleaner, easier to maintain, and is less error-prone. Without the function, we would have to write the code multiple times for the same work.

//Code without function
let result = 5 * 3
console.log(result)//15

let result2 = 10 * 4
console.log(result2)//40



/* **********************************************************/


//Code with function
function multiply(a, b) {
  return a * b
}

console.log(multiply(5, 3))//15
console.log(multiply(10, 4))//40
console.log(multiply(10, 6))//60
console.log(multiply(9, 4))//36

Function as values

In JavaScript, functions are like "First-Class Citizens." It is one way of saying a function is just another type of data, like a string or a number. It means

  • We can store them in a variable

  • We can also pass them to another function to be executed according to the user's requirements

  • We can also return them from functions


const buyChocolateForMe = function() { 

console.log("Hello! Ram, Here is your Chocolate"); 

};

buyChocolateForMe(); // Hello! Ram, Here is your Chocolate

Passing a function as a value

function sayHelloToMe() {
  console.log("Hello Abhishek");
}

function executeMyFunction(fn) {
  fn(); // calling the function passed
}

execute(sayHelloToMe);
//Here we are not passing the result of syaHelloToMe but we are just  passing the function istself

What is a Callback Function?

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

function buyLaptopForMe(prodcut,callback){
    console.log(`You Successfully bought the ${prodcut}.`);
    callback();
}

function thankYouMessage(){

console.log("Thank You for Buying the Prodcut .Please visit     again , Bye!");

}

buyLaptopForMe("MacBook Pro", thankYouMessage);


//Here we excuting the callback function later after consoling the message

Output

You Successfully bought the MacBook Pro. 
Thank You for Buying the Prodcut .Please visit again , Bye!

Why are callbacks used in asynchronous programming?

JavaScript is single-threaded , meaning it can only do one thing at a time. If a user gives it a task to read big file with 5000 or 10000 thousands lines of code or say download a 1 GB file or fetch some data from the database from the farway , the whole website would freeze until it's done.

To prevent the blocking or freezing , we use Asynchronous Programming.

We say to JavaScript:

Go start and read the file. I don't want to wait, so here is a callback function. Run it whenever you're finished

Example code without a callback function

console.log("Start reading file with some time");

setTimeout(function() {
 console.log("Inside timeout finised executing"); 
}, 2000);

console.log("End reading file ");

Output of the above code

Start reading file with some time
End reading file 
Inside timeout finised executing

The setTimeout is executed later because it is async and it runs later

Using callback

function fetchMyFileData(callback) {

  setTimeout(function() {
    console.log("Data fetched successfully");
    callback();//precssMyData get excuted 
  }, 2000);

}

function processMyData() {
  console.log("Processing data...");
}

fetchMyFileData(processMyData);

//Output:
//Data fetched successfully 
//Processing data...

In the above the code, fetchMyFileData function is called and in it processMyData is passed as a callback function .After 2 second the console statement inside the setTImeout get executed and then the callback function is executed.

We see callbacks everywhere in modern JS development:

Timers: setTimeout(() => { ... }, 1000) runs code after a delay.

Events: button.addEventListener('click', () => { ... }) runs code only when a user clicks.

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

Data Fetching: Getting info from a database or an API.

function getUser(callback) {
 
setTimeout(() => {
callback({ name: "Ram" }); 
}, 1000); }

getUser(function(user) { 
console.log(user.name); 
});

Passing functions as arguments

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(10, 5, add)); // 15
console.log(calculate(4, 5, multiply)); // 20

Problems with Callback

When multiple asynchronous operations depend on each other, callbacks get deeply nested, making the code hard to read and maintain.This is known as callback Hell

function step1(callback) {
    setTimeout(() => {
        console.log("Step 1 completed");
        callback();
    }, 1000);
}

function step2(callback) {
    setTimeout(() => {
        console.log("Step 2 completed");
        callback();
    }, 1000);
}

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

step1(() => {
    step2(() => {
        step3(() => {
            console.log("All steps completed");
        });
    });
});




As the number of steps increases in our code , the nesting grows deeper and deeper, which makes the code difficult to manage ,read and debug.

To solve the issue of callback hell, we use

  • Promises

  • async/await