# Understanding Async/Await in JavaScript

JavaScript is famous for making websites interactive but there is one thing every developer struggles with is **handling asynchronous operations**.

Imagine, you order chai at a shop, While chaiwala prepares your chai, you don’t stand there. You chat with friends, check your phone. Once chai is ready, you continue.

Thats how JavaScript handles async tasks.

Before `async/await`, developers used **callbacks** and later **Promises**. But complex async code quickly became hard to read. To solve this, JavaScript introduced **async/await** which was a cleaner and more readable way to work with asynchronous code.

## Why Async/Await Was Introduced

Before async/await, developers used Promises like this:

```javascript
fetchData()
  .then((data) => {
    return processData(data);
  })
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.log(error);
  });
```

This works fine for small tasks.

But when multiple async operations are used together code starts looking like confusing and difficult to follow.

Async/await was introduced in ES2017 to:

*   Improve readability
    
*   Make asynchronous code look synchronous
    
*   Simplify error handling
    
*   Reduce Promise chaining complexity  
    

In simple words

> Async/await is syntactic sugar over Promises.

That means it does not replace Promises internally -> it simply provides a cleaner syntax to work with them.

## How Async Functions Work

An `async` function always returns a Promise.

**Syntax :**

```javascript
async function greet() {
  return "Namaste Developer";
}
```

Even though we return a string, JavaScript automatically wraps it inside a Promise.

**Equivalent Promise version**

```javascript
function greet() {
  return Promise.resolve("Namaste Developer!");
}
```

## Understanding the Await Keyword

The `await` keyword pauses execution of an async function until the Promise resolves.

Here is an example,

```javascript
function orderChai() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Chai is Ready");
    }, 2000);
  });
}

async function serveCustomer() {
  console.log("Making chai...");

  const result = await orderChai();

  console.log(result);
}

serveCustomer();

// OUTPUT
// Making chai...
// (2 second pause)
// Chai is Ready
```

Here is what happens:

1.  `orderChai()` returns a Promise
    
2.  `await` pauses execution
    
3.  JavaScript waits for the Promise to resolve
    
4.  Execution resumes
    

## Error Handling with Async Code

One of the advantages of async/await is clean error handling. Instead of `.catch()`, we can use `try/catch`.

Here is an Example,

```javascript
function paymentSuccessful() {
  return new Promise((resolve, reject) => {
    const success = false;

    setTimeout(() => {
      if (success) {
        resolve("Payment Successful");
      } else {
        reject("Payment Failed");
      }
    }, 2000);
  });
}

async function processPayment() {
  try {
    const message = await paymentSuccessful();

    console.log(message);

  } catch (error) {
    console.log("Error:", error);
  }
}

processPayment();

// OUTPUT
// Error: Payment Failed
```

## Promise vs Async/Await Flow

**Using Promises**

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

**Using Async/Await**

```javascript
async function handleOrders() {
  try {
    const user = await getUser();

    const orders = await getOrders(user);

    const result = await processOrders(orders);

    console.log(result);

  } catch (err) {
    console.log(err);
  }
}
```

### Difference

| Promises | Async/Await |
| --- | --- |
| Uses `.then()` chaining | Looks synchronous |
| Harder to read in complex flows | Cleaner syntax |
| Nested chains possible | Easier maintenance |
| Error handling split | Centralized with `try/catch` |

## Important Things to Remember

1.  Await Only Works Inside Async Functions
    
    ```javascript
    await fetchData();  // Wrong
    
    async function getData() { // Correct Way
        await fetchData();
    }
    ```
    
2.  Async Functions Always Return Promises
    
    ```javascript
    async function test() {
        return 10;
    }
    
    // ACTUALLY RETURNS
    Promise { 10 } 
    ```
    
3.  Await Does Not Block Entire JavaScript. It only pauses the current async function and Other operations continue running normally.
    

## When Should You Use Async/Await?

**Use async/await when:**

*   Fetching API data
    
*   Reading files Database operations
    
*   Delayed tasks
    
*   Sequential async operations
    

**Examples :**

*   Loading IPL scores from an API
    
*   Processing UPI payments
    
*   Fetching weather updates
    
*   Uploading Aadhaar documents
    

## Limitations of Async/Await

Although async/await improves readability, it has some drawbacks:

1.  Sequential Execution Can Be Slower
    
    ```javascript
    await task1();
    await task2();
    
    // Here, task2 waits for task1
    
    
    // Sometimes running tasks in parallel using Promise.all() is faster.
    const [user, posts] = await Promise.all([ getUser(), getPosts() ]); 
    ```
    
2.  Still Based on Promises  
    Async/await is not a replacement for Promises. Under the hood, it still uses Promises internally.
    

## Conclusion

If you’re learning modern JavaScript, mastering async/await is essential. You’ll use async programming everywhere.

And once you start using async/await, going back to long Promise chains feels like returning from 5G to 2G network.

Thanks for Reading.
