# Callbacks in JavaScript

JavaScript treats functions like any other variable. As you pass a string or a number to a function, you can pass a whole function to another function. You can also assign them to variables, or return them from other functions.

## What is a Callback Function?

A **callback function** is simply a function that we pass to another function as an argument, with the expectation that the outer function will execute our function at some time.

Here is an example,

```javascript
// function that is to be passed as callback
function serveChai(type) {
    console.log(`Here is your ${type} chai!`);
}

// function that accepts a callback function and uses it.
function prepareChai(type, callback) {
    console.log(`Boiling milk and adding ${type} chai patti...`);
    callback(type); 
}

prepareChai('Masala', serveChai); // Passing serveChai function
// Output
// Boiling milk and adding Masala chai patti...
// Here is your Masala chai!
```

## Why Callbacks are Used in Asynchronous Programming ?

JavaScript is single threaded that means it can only do one thing at a time. If it stops to wait for a heavy task to finish our webpage will freeze.

Callbacks are the solution to this problem. It allows JavaScript to say "Start this heavy task in background and when it is done run this callback function." Simultaneously, I am going to keep running the rest of the code.

Here is an Example

1.  Imagine you go to a shop to order Samosa. They are currently frying samosas. You place your order and pay. The cashier do not make you stand at the counter blocking the line. Instead, they give you a token number.
    
2.  You step aside and chat with your friends (running the rest of the code).
    
3.  When the Samosas are ready, the counter shouts your token number (the callback is triggered), and you collect your food.
    

Here is how that looks in code using setTimeout, which creates a asynchronous delay.

```javascript
console.log("1. Placed order for 2 Samosas at the counter.");

// setTimeout takes a callback function and a delay in milliseconds
setTimeout(function() {
    console.log("3. Token 42, your Samosas are ready! (Callback executed)");
}, 3000); // Wait 3 seconds

console.log("2. Gone aside to chat with friends while waiting...");

// Output

// 1. Placed order for 2 Samosas at the counter.
// 2. Gone aside to chat with friends while waiting...
// 3. Token 42, your Samosas are ready! (Callback executed)
```

## Callback Usage in Common Scenarios

You will see callbacks everywhere in modern JavaScript. Here are a few common places,

### 1\. Event Listeners

When interacting with the DOM you don't know *when* a user will click a button. You provide a callback to run when the event occurs.

```javascript
const tatkalButton = document.getElementById("bookTicket");

tatkalButton.addEventListener("click", function() {
    console.log("Trying to book Tatkal ticket.");
});
```

### 2\. Array Methods

Methods like `map`, `filter`, and `forEach` take a callback function to know what to do with each item of the array.

```javascript
const streetFood = ["Vada Pav", "Pani Puri", "Dosa", "Momos"];

// callback function runs for every item in array
streetFood.forEach(function(item) {
    console.log(`I would love to eat ${item} today.`);
});

// Output
// I would love to eat Vada Pav today.
// I would love to eat Pani Puri today.
// I would love to eat Dosa today.
// I would love to eat Momos today.
```

## The Problem: Callback Nesting (Callback Hell)

Callbacks are great for simple tasks, but they get messy when you have **dependent asynchronous tasks.**

Imagine organising a wedding. These things to be done in a specific order:

1.  Book Marriage Hall.
    
2.  After booking hall, hire Caterer.
    
3.  After finalizing menu, print Invitation Cards.
    
4.  After printing, distribute them to relatives.
    

If all these was asynchronous database calls, our code would look like this.

```javascript
bookMarriageHall(date, function(hallDetails) {
    
    hireCaterer(hallDetails, function(menuDetails) {
        
        printInvitationCards(menuDetails, function(cards) {
            
            distributeCards(cards, function(relativesResponse) {
                console.log("Wedding Prep is Done now");
            });
            
        });
        
    });
    
});
```

Here is the flow Diagram of the above code,

![](https://cdn.hashnode.com/uploads/covers/696a48f1be835070a55feb09/d3f4331d-5bca-4eaf-a610-1bc0f0fff55a.png align="center")

### The "Pyramid of Doom"

Notice how code keeps shifting to right, creating a triangle or pyramid like shape. This is popularly called **Callback Hell**.

**Why is this a problem?**

*   **Readability:** It is incredibly difficult to read and track the flow of logic.
    
*   **Error Handling:** If an error happens while printing cards, passing that error through all those functions is difficult and can produce bugs.
    
*   **Maintainability:** If we have to add a new step (like booking a photographer) in middle of this pyramid is not very doable.
    

Because of Callback Hell, JavaScript developers introduced **Promises** and **Async/Await**, which are modern, cleaner ways to handle asynchronous code while avoiding this deeply nested trap.

However, understanding callbacks remains essential as they are the foundational block on which all of JavaScripts async behavior is built.

Thanks for Reading.
