# Async Code in Node.js

## Why async code exists in Node.js .

So async code exists because of a problem in how JavaScript executes code.

### Problem Statement :-

*   JavaScript code runs line by line, from top to bottom. Now imagine a function that makes a database call. We all know the database can be on another continent, so it may take time. Let’s assume it takes 1 minute to complete that database call successfully.
    
*   Now the problem is that while this function is waiting for the database response, the rest of the code will also stop executing. This means the current function holds the execution and blocks the whole code.
    
*   This becomes a big problem. For example, if we are uploading a 1GB file to a server and it takes time, then the whole application will be blocked. Other users will not be able to access the service, and the application may even feel like it has crashed.
    

### Solution :-

*   To solve this problem, we needed a solution.
    
*   So the idea was, whenever we know a function will take time to execute, we should run that function in the background. When it successfully completes its request, then it should execute its result without blocking the rest of the code.
    
*   This is how asynchronous methods came. Any async code runs in the background, and the rest of the code is not affected. This is why it is also called non-blocking code.
    

## Callback based async execution .

So in a callback function, what happens is that you create a function and pass it into another function.

*   Now the function in which you passed this callback function will execute first. After it finishes its execution, then the callback function will be executed.
    
*   Basically, it means, Take this function, and when your work is completed, call it or return it to me so I can get the data.
    
*   So it tells that whenever its task is finished, then execute the callback function.
    

```javascript
function getData(callback) {
  setTimeout(() => {
    console.log("Data fetched from server");
    callback();
  }, 2000);
}

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

getData(processData);
```

## Problems with nested callbacks .

So, by callback nesting or callback hell, we mean having multiple callbacks inside one another.

*   This happens because when you get some value, after performing an operation on it, you pass it to another callback function. Then that callback extracts some data and passes it to another function. In this way, a chain is created.
    
*   If this chain goes too deep, the code becomes very hard to read and is not standardized. That's why it is called callback nesting or also can say callback hell. You can see this problem clearly in the code example below.
    

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

Here you can see there is one function, and inside it a callback is passed as an argument. Then inside that, there is another function passed as a callback. This is how a chain is created.

## Promise-based async handling .

In promise-based approach, basically we have a Promise which is used to handle asynchronous operations.

*   Inside a Promise, there are two states: resolve and reject. If the operation is successful, it returns resolve. If it fails, it returns reject.
    
*   So whenever a Promise is returned, it returns a result that we can work with. We then perform operations on it. If it is resolved, we handle it in one way, and if it is rejected, we handle it in another way, like showing an error or message.
    
*   We handle all of this using Promise instance methods.
    

## Benefits of promises.

*   Promises make asynchronous code much easier to handle and understand compared to callback-based code. They help avoid “callback hell,” where multiple nested callbacks make the code hard to read and maintain.
    
*   With promises, code becomes more structured and clean because we can attach .then() for success and .catch() for errors in a clear flow. This improves readability and makes debugging simpler.
    
*   Promises also allow better control over asynchronous operations, especially when dealing with multiple tasks one after another or in parallel.
    

> ### Simple Example :-
> 
> 1.  If a promise is rejected, then whatever error comes is directly handled in the .catch() block, where we can catch it and return or show it.
>     
> 2.  But if the promise is resolved, meaning it is successful, then we get the actual data. For example, if we assume a database call, then we receive data from there.
>     
> 3.  After getting the data, we can use a .then() call to access it. Now, if we want to do further processing on this data, we can pass it to the next then() function.
>     
> 4.  In this way, we can create a chain of .then() calls and keep handling and processing the data step by step.
>     

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">So with my above explanation i hope you understand what i learn and what's my thought process on Async code in Node.js: Callbacks and Promises in JavaScript.</div>
</div>
