# Async/Await in JavaScript: Writing Cleaner Asynchronous Code

Handling asynchronous operations is a core part of JavaScript—whether it's fetching data from an API, reading files, or working with timers.

Before `async/await`, developers relied heavily on **callbacks** and **promises**, which often led to complex and hard-to-read code.

This is where `async/await` comes in.

* * *

## 🔹 Why Async/Await Was Introduced

### 🚨 The Problem Before

#### 1\. Callback Hell

```js
getData(function(a) {
  processData(a, function(b) {
    saveData(b, function(c) {
      console.log(c);
    });
  });
});
```

❌ Hard to read ❌ Difficult to debug ❌ Deep nesting

* * *

#### 2\. Promise Chains

```js
getData()
  .then(a => processData(a))
  .then(b => saveData(b))
  .then(c => console.log(c))
  .catch(err => console.error(err));
```

✔ Better than callbacks ❌ Still not very intuitive for beginners ❌ Can grow complex

* * *

### ✅ Solution: Async/Await

*   Built on top of promises
    
*   Makes asynchronous code look like synchronous code
    
*   Improves readability and maintainability
    

👉 **Async/Await is syntactic sugar over promises**

* * *

## 🔹 How Async Functions Work

An `async` function **always returns a promise**.

```js
async function greet() {
  return "Hello";
}

greet().then(console.log); // "Hello"
```

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

* * *

## 🔹 The Await Keyword

The `await` keyword **pauses execution** until a promise resolves.

### 👉 Example

```js
function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => resolve("Data received"), 2000);
  });
}

async function getData() {
  const data = await fetchData();
  console.log(data);
}

getData();
```

### 🔍 What Happens Here?

*   `await fetchData()` waits for the promise to resolve
    
*   Execution pauses inside the function
    
*   No `.then()` needed
    

* * *

## 🔹 Real-World Example (API Call)

```js
async function fetchUser() {
  const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
  const data = await response.json();

  console.log(data);
}

fetchUser();
```

✔ Clean ✔ Easy to read ✔ Looks synchronous

* * *

## 🔹 Error Handling with Async/Await

With promises, errors are handled using `.catch()`.

With async/await, we use **try...catch**.

```js
async function getData() {
  try {
    const res = await fetch("https://invalid-url.com");
    const data = await res.json();
    console.log(data);
  } catch (error) {
    console.error("Error:", error);
  }
}
```

✔ Cleaner error handling ✔ Similar to synchronous code

* * *

## 🔹 Comparison: Promise vs Async/Await

### Promise Version

```js
fetchData()
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));
```

* * *

### Async/Await Version

```js
async function getData() {
  try {
    const res = await fetchData();
    const data = await res.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}
```

* * *

### 🔥 Key Differences

| Feature | Promises | Async/Await |
| --- | --- | --- |
| Syntax | `.then().catch()` | `try...catch` |
| Readability | Moderate | High |
| Error Handling | Chain-based | Block-based |
| Learning Curve | Medium | Easier |

* * *

## 🧠 Mental Model

*   `async` → "This function returns a promise"
    
*   `await` → "Wait here until the promise resolves"
    

* * *

## 🚀 Practical Use Cases

### 1\. Sequential API Calls

```js
async function loadData() {
  const user = await fetchUser();
  const posts = await fetchPosts(user.id);

  console.log(posts);
}
```

* * *

### 2\. Parallel Execution (Important Optimization)

```js
async function loadData() {
  const [user, posts] = await Promise.all([
    fetchUser(),
    fetchPosts()
  ]);

  console.log(user, posts);
}
```

👉 Runs both requests at the same time (faster)

* * *

### 3\. Cleaner Loops

```js
async function processItems(items) {
  for (const item of items) {
    const result = await process(item);
    console.log(result);
  }
}
```

* * *

## ⚠️ Common Mistakes

### ❌ Using await outside async

```js
const data = await fetchData(); // ❌ Error
```

✔ Must be inside an `async` function

* * *

### ❌ Blocking Unnecessarily

```js
const a = await task1();
const b = await task2();
```

👉 Runs sequentially (slow)

✔ Use `Promise.all()` when possible

* * *

### ❌ Forgetting Error Handling

```js
async function getData() {
  const res = await fetch(url); // ❌ may crash
}
```

✔ Always wrap with `try...catch`
