Skip to main content

Command Palette

Search for a command to run...

Async/Await in JavaScript: Writing Cleaner Asynchronous Code

Updated
4 min read

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

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

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.

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

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)

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.

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

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

Async/Await Version

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

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

  console.log(posts);
}

2. Parallel Execution (Important Optimization)

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

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

⚠️ Common Mistakes

❌ Using await outside async

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

✔ Must be inside an async function


❌ Blocking Unnecessarily

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

👉 Runs sequentially (slow)

✔ Use Promise.all() when possible


❌ Forgetting Error Handling

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

✔ Always wrap with try...catch