# Callbacks in JavaScript: Why They Exist

## Introduction

JavaScript is powerful because functions are **first-class citizens** — meaning they can be treated like values.

You can:

*   Store functions in variables
    
*   Pass functions as arguments
    
*   Return functions from other functions
    

This ability is what makes **callbacks** possible.

## What is a Callback Function?

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

### Basic Example

```js
function greet(name) {
  console.log("Hello " + name);
}

function processUserInput(callback) {
  const name = "Pratham";
  callback(name);
}

processUserInput(greet);
```

Here:

*   `greet` is the callback
    
*   `processUserInput` executes it
    

## Functions as Values in JavaScript

Before understanding callbacks deeply, you need this concept:

```js
function sayHello() {
  console.log("Hello!");
}

const fn = sayHello; // function assigned to variable
fn(); // Hello!
```

This shows:

*   Functions behave like normal variables
    

* * *

## Passing Functions as Arguments

```js
function executeTask(task) {
  console.log("Starting task...");
  task();
}

executeTask(function () {
  console.log("Task completed!");
});
```

👉 Output:

```plaintext
Starting task...
Task completed!
```

This is the **core idea behind callbacks**.

## Why Callbacks Are Used (Async Programming)

JavaScript is **single-threaded**, but it handles async operations like:

*   API calls
    
*   File reading
    
*   Timers
    

👉 Instead of blocking execution, JavaScript uses callbacks.

### Without Callback (Blocking Concept)

```js
const data = getDataFromServer(); // imagine delay
console.log(data);
```

Problem:

*   Code waits → bad performance
    

### With Callback (Non-blocking)

```js
function fetchData(callback) {
  setTimeout(() => {
    callback("Data received");
  }, 2000);
}

fetchData(function (data) {
  console.log(data);
});
```

Output after 2 seconds:

```plaintext
Data received
```

JS continues running while waiting

## Common Callback Use Cases

### 1\. Timers

```js
setTimeout(() => {
  console.log("Runs after 2 seconds");
}, 2000);
```

### 2\. Event Handling

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

### 3\. API Calls (Old Way)

```js
fetchData(function (response) {
  console.log(response);
});
```

## The Problem: Callback Nesting

When callbacks are nested inside callbacks → code becomes messy.

### Callback Hell Example

```js
loginUser(function (user) {
  getUserData(user, function (data) {
    getOrders(data, function (orders) {
      console.log(orders);
    });
  });
});
```

Problems:

*   Hard to read
    
*   Hard to debug
    
*   Hard to maintain
    

## Conceptual Understanding of the Problem

Think of it like:

“Do this → then inside it do this → then inside that do this…”

It creates a **pyramid structure**:

```plaintext
level 1
  level 2
    level 3
      level 4
```

This is called **Callback Hell** or **Pyramid of Doom**.

## How It Was Solved Later

To fix callback problems, JavaScript introduced:

*   **Promises**
    
*   **Async/Await**
    

But callbacks are still important because:

*   They are the **foundation of async JS**
    
*   Many APIs still use them
    

## Diagram Ideas

### 1\. Function Flow

```plaintext
Main Function
   ↓
Calls Another Function (Callback)
   ↓
Callback Executes Later
```

### 2\. Nested Callback Flow

```plaintext
loginUser()
  ↓
getUserData()
  ↓
getOrders()
  ↓
display()
```

## Summary

*   Functions in JavaScript behave like values
    
*   Callbacks = functions passed into other functions
    
*   Used to handle async operations without blocking
    
*   Widely used in timers, events, APIs
    
*   Major drawback → **callback nesting (callback hell)**
    
*   Later improved using **Promises & async/await**
