# Async Code in Node.js: Callbacks and Promises

When building applications in Node.js, many operations take time to complete.

Examples:

*   Reading files
    
*   Fetching data from APIs
    
*   Connecting to databases
    
*   Waiting for user input
    

If Node.js waited for each task to finish before moving forward, applications would become slow and inefficient.

This is why Node.js uses **asynchronous code**.

In this article, we’ll understand:

*   Why async code exists in Node.js
    
*   Callback-based asynchronous execution
    
*   Problems with nested callbacks
    
*   Promise-based async handling
    
*   Benefits of promises
    

Let’s begin with a real-world example.

* * *

## Why Does Async Code Exist in Node.js?

Imagine reading a large file from your computer.

If Node.js stopped everything until the file finished loading, the entire application would freeze.

Instead, Node.js starts the file-reading task and continues doing other work.

When the file is ready, Node.js handles the result later.

This is called **asynchronous programming**.

* * *

### Synchronous vs Asynchronous Code

### Synchronous Code

```javascript
console.log("Start");

console.log("Reading file...");

console.log("End");
```

Output:

```id="rj77zn"
Start
Reading file...
End
```

The code runs line by line in order.

* * *

### Asynchronous Example

Node.js provides asynchronous functions like `fs.readFile()`.

Example:

```javascript
const fs = require("fs");

console.log("Start");

fs.readFile("demo.txt", "utf8", (err, data) => {
  console.log(data);
});

console.log("End");
```

Possible output:

```id="w7y2mk"
Start
End
File content here
```

Notice:

*   Node.js does not wait for the file to finish reading
    
*   It continues executing the next lines
    
*   The callback runs later when the file is ready
    

* * *

## What is a Callback?

A **callback** is a function passed into another function to run later.

Example:

```javascript
function greet(name, callback) {
  console.log("Hello " + name);

  callback();
}

function sayBye() {
  console.log("Goodbye");
}

greet("Abhi", sayBye);
```

Output:

```id="5dr4u7"
Hello Abhi
Goodbye
```

Here:

*   `sayBye` is passed as a callback
    
*   It executes after the greeting
    

* * *

### Callback-Based Async Execution

Let’s understand async flow step by step.

Example:

```javascript
const fs = require("fs");

console.log("1. Start Reading");

fs.readFile("demo.txt", "utf8", (err, data) => {
  console.log("2. File Content:", data);
});

console.log("3. Continue Execution");
```

Output:

```id="m4lmv9"
1. Start Reading
3. Continue Execution
2. File Content: Hello World
```

* * *

### How the Callback Flow Works

```id="3mwpx5"
Start Program
      ↓
Start File Reading
      ↓
Continue Other Code
      ↓
File Reading Completes
      ↓
Callback Function Executes
```

This is the foundation of asynchronous programming in Node.js.

* * *

### Problems with Nested Callbacks

Callbacks work well initially, but deeply nested callbacks can make code difficult to read.

Example:

```javascript
loginUser(function(user) {
  getPosts(user, function(posts) {
    getComments(posts, function(comments) {
      console.log(comments);
    });
  });
});
```

This structure becomes hard to manage.

This problem is often called:

```id="ym1iw9"
Callback Hell
```

Problems include:

*   Hard to read
    
*   Difficult to debug
    
*   Deep nesting
    
*   Poor maintainability
    

* * *

## Introduction to Promises

Promises were introduced to make asynchronous code cleaner and easier to manage.

A Promise represents a value that may be available:

*   Now
    
*   Later
    
*   Or never
    

* * *

### Creating a Promise

Example:

```javascript
const promise = new Promise((resolve, reject) => {
  let success = true;

  if (success) {
    resolve("Operation Successful");
  } else {
    reject("Operation Failed");
  }
});
```

A promise has two possible outcomes:

*   `resolve()` → success
    
*   `reject()` → failure
    

* * *

### Handling Promises

We use:

*   `.then()` for success
    
*   `.catch()` for errors
    

Example:

```javascript
promise
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
    console.log(error);
  });
```

Output:

```id="o5b3p2"
Operation Successful
```

* * *

## Promise-Based Async Handling

Let’s rewrite a file-reading example using promises.

Example:

```javascript
const fs = require("fs").promises;

fs.readFile("demo.txt", "utf8")
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
```

This looks cleaner compared to nested callbacks.

* * *

## Callback vs Promise Readability

## Callback Style

```javascript
getUser(function(user) {
  getOrders(user, function(orders) {
    console.log(orders);
  });
});
```

* * *

### Promise Style

```javascript
getUser()
  .then((user) => getOrders(user))
  .then((orders) => console.log(orders))
  .catch((err) => console.log(err));
```

Promises reduce nesting and improve readability.

* * *

### Benefits of Promises

Promises provide several advantages:

✅ Cleaner code

✅ Better readability

✅ Easier error handling

✅ Avoid callback hell

✅ Better async chaining

This is why modern Node.js applications heavily use promises.

* * *

### Promise Lifecycle

A promise has three states.

```id="z0ajz7"
Pending
   ↓
Resolved  OR  Rejected
```

### States

| State | Meaning |
| --- | --- |
| Pending | Operation still running |
| Resolved | Operation successful |
| Rejected | Operation failed |

* * *

## Practice Assignment

Try these tasks yourself.

* * *

### 1\. Callback Example

Create a function that waits 2 seconds and then prints a message using a callback.

Example:

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

* * *

### 2\. Promise Example

Create a promise that resolves after 2 seconds.

Example:

```javascript
const promise = new Promise((resolve) => {
  setTimeout(() => {
    resolve("Data loaded");
  }, 2000);
});
```

* * *

### 3\. Handle the Promise

Use `.then()` to print the resolved value.

* * *

And now, you know what Callbacks and Promises in Node.js are.

If you have any doubt or want to connect, feel free to drop a comment — I’d be happy to help.

Thanks for reading, and see you in the next blog!

Peace ✌️ and Happy Learning!
