DEV Community

Souvik Guha Roy
Souvik Guha Roy

Posted on

Async/Await in JavaScript: Writing Cleaner Asynchronous Code

Handling asynchronous code in JavaScript used to be messy—first with callbacks, then with promises.

Then came async/await, making async code look and behave more like synchronous code.

In this blog, we’ll understand why async/await was introduced, how it works, and why it makes your code cleaner and easier to read.


🚨 The Problem Before Async/Await

❌ Callback Hell

```js id="cb1"
setTimeout(() => {
console.log("Step 1");

setTimeout(() => {
console.log("Step 2");

setTimeout(() => {
  console.log("Step 3");
}, 1000);
Enter fullscreen mode Exit fullscreen mode

}, 1000);

}, 1000);




😵 Hard to read
😵 Hard to maintain

---

### ❌ Promises (Better, But Still Verbose)



```js id="pr1"
fetchData()
  .then(data => {
    return processData(data);
  })
  .then(result => {
    console.log(result);
  })
  .catch(err => {
    console.error(err);
  });
Enter fullscreen mode Exit fullscreen mode

✔ Better than callbacks
❌ Still chained and less readable


💡 Why Async/Await Was Introduced

Async/await was introduced to:

  • Simplify asynchronous code
  • Improve readability
  • Avoid chaining .then()
  • Make code look synchronous

👉 It is syntactic sugar over promises


🧠 What Is an async Function?

An async function always returns a promise.

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






```js id="async2"
greet().then(console.log); // Hello
Enter fullscreen mode Exit fullscreen mode

⏳ What Does await Do?

The await keyword pauses execution until a promise resolves.

```js id="await1"
async function getData() {
const result = await fetchData();
console.log(result);
}




👉 It makes async code look synchronous.

---

## 📊 Async Function Flow



```id="viz1"
async function starts
   ↓
await pauses execution
   ↓
promise resolves
   ↓
execution resumes
Enter fullscreen mode Exit fullscreen mode

🔄 Example: Promises vs Async/Await


❌ Using Promises

```js id="compare1"
fetchData()
.then(data => processData(data))
.then(result => console.log(result))
.catch(err => console.error(err));




---

### ✅ Using Async/Await



```js id="compare2"
async function run() {
  try {
    const data = await fetchData();
    const result = await processData(data);
    console.log(result);
  } catch (err) {
    console.error(err);
  }
}
Enter fullscreen mode Exit fullscreen mode

👉 Much cleaner and easier to read


🛠️ Error Handling with Async/Await

Use try...catch to handle errors.

```js id="err1"
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.log("Error:", error.message);
}
}




---

## ⚠️ Important Notes

* `await` works only inside `async` functions
* It pauses execution **without blocking the entire program**
* Always handle errors using `try...catch`

---

## 🧩 Real-World Example



```js id="real1"
async function fetchUser() {
  try {
    const response = await fetch("https://api.example.com/user");
    const data = await response.json();

    console.log(data);
  } catch (err) {
    console.error("Failed to fetch user");
  }
}
Enter fullscreen mode Exit fullscreen mode

🧠 Why Async/Await Is Better

✅ Readability

Looks like synchronous code.

✅ Cleaner Logic

No .then() chaining.

✅ Easier Debugging

Errors handled in one place.


📊 Promise vs Async/Await Flow

Promises:
Task → then → then → catch

Async/Await:
Task → await → result (linear flow)
Enter fullscreen mode Exit fullscreen mode

🎯 When to Use Async/Await

Use it when:

  • Working with APIs
  • Handling multiple async operations
  • You want clean, readable code

🚀 Final Thoughts

Async/await is one of the most important features in modern JavaScript.

It helps you:

  • Write cleaner async code
  • Avoid callback hell
  • Handle errors gracefully

🧠 Quick Summary

  • async → returns a promise
  • await → waits for promise
  • Cleaner than promises
  • Uses try...catch for errors

Top comments (0)