Skip to main content

Command Palette

Search for a command to run...

Callbacks in JavaScript: Why They Exist

Updated
•3 min read•View as Markdown
Callbacks in JavaScript: Why They Exist
B
I am a third-year undergrad student at Chandigarh University. I am into building backend and applied AI stuff using the modern technologies. I loves to document my learning through the blogs so that I can contribute to the community.

Before starting anything we can first get know how functions in JavaScript behaves like a value. It means we can simply treat this functions as number which can be stored inside a variable, can be passed as arguments to another function and we can even return them from other functions.

Functions as Values

Let's understand this with the following examples:

//Function as value
function add(a, b) {
    console.log(a + b)
}

const sum = add //<- Here the reference of the add function gets saved to the sum variable

sum(2, 3) //5

Functions as Arguments

function processUser(callback) {
  console.log("Processing user...");
  callback();
}

function done() {
  console.log("Done!");
}

processUser(done); //We have passed the done function as the arg to processUser function

What is Callback ?

A callback is simply a function that is passed into another to function to be executed later. Let's understand this with a better example:

//We are trying to make a API call which takes some time
fucntion fetchData() {
    //It will take time
}
const data = fetchData()
console.log(data) // It will be undefined because data still dont exists
//Now solve the above by using callbacks where we want to run fetchData function after the data has arrived

function fetchData(callback) {
  setTimeout(() => {
    console.log("Data fetched");
    callback(); // <- The callback will run after Data Fetched is logged
  }, 1000);
}

fetchData(() => { // This function will behave like a callback which is passed as argument to fetchData function
  console.log("Now process data"); 
});
// NOTE: Don't ever directly call the function like 
//setTimeout(callback(), 1000) <- It will immediately run the function

Now here the reason of using callbacks in asynchronous programming comes into picture.

In the above code we see that the callback is actually getting executed after timeout is completed.

Like setTimeout takes a callback as the first parameter and time in ms as second parameter. So it actually means: Runt the callback function after the timer ends. Simple Analogy is this:

Yeh Kaam hone ke baad callback ko call kr dena!!

Callback Hell

Now using callbacks sometimes causes issues like:

getUser((user) => {
  getOrders(user.id, (orders) => {
    getPayment(orders[0], (payment) => {
      console.log(payment);
    });
  });
});

In the above code we are actually getting stuck in the callback hell where each function depends on another function and that function again depends on another function.

This decreasing the code readability, debugging becomes difficult and catching error is a nightmare and here come the modern approach to solve this issue that is Promises:

getUser()
  .then((user) => getOrders(user.id))
  .then((orders) => getPayment(orders[0]))
  .then((payment) => console.log(payment));

The above is further made simpler with the use of Async/Await syntax like:

async function process() {
  const user = await getUser();
  const orders = await getOrders(user.id);
  const payment = await getPayment(orders[0]);

  console.log(payment);
}