Skip to main content

Command Palette

Search for a command to run...

Async/Await in JavaScript: Writing Cleaner Asynchronous Code

Write Asynchronous code that looks synchronous and easy to understand.

Updated
3 min read
Async/Await in JavaScript: Writing Cleaner Asynchronous Code

The Problem: Messy Asynchronous Code

Before async/await , we used callbacks and promises.

Callback Hell

getUser(user => {
  getOrders(user, orders => {
    getItems(orders, items => {
      console.log(items);
    });
  });
});

Hard to read
Hard to debug

Promises (Better, but still messy)

getUser()
  .then(user => getOrders(user))
  .then(orders => getItems(orders))
  .then(items => console.log(items))
  .catch(err => console.log(err));

Better than callbacks, but still not very intuitive.

Why Async/Await Was Introduces?

To make async code:

  • Cleaner

  • More readable

  • Easier to debug

Key Idea

Async/Await = Syntactic sugar over Promises

It doesn’t replace promises — it makes them easier to use.

How Async Functions Work

An async functions always returns a promise.

Example:

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

Behind the scenes

return "Hello"
   ↓
Promise.resolve("Hello")

The await keyword

await 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();

Visual Timeline

Start → wait (2 sec) → data received → continue

Real Power: Clean Code

Promise style:

fetchData()
  .then(data => processData(data))
  .then(result => console.log(result))
  .catch(err => console.log(err));

Async/Await Style:

async function run() {
  try {
    const data = await fetchData();
    const result = await processData(data);
    console.log(result);
  } catch (err) {
    console.log(err);
  }
}

Visual Comparison:

Promises → chained
Async/Await → step-by-step

Error Handling With Async/Await

Use try...catch for errors.

Example:

async function fetchData() {
  throw new Error("Something went wrong");
}

async function run() {
  try {
    await fetchData();
  } catch (error) {
    console.log(error.message);
  }
}

Flow:

await → error  → catch handles it 

Conceptual Understanding

Think of await as:

"Wait here until this task is finished."

Code pauses → result comes → continues

Comparison: Promises vs Async/Await

Feature        | Promises         | Async/Await
---------------|------------------|-------------------
Syntax         | .then() chain    | clean & linear
Readability    | Medium           | High 
Error Handling | .catch()         | try...catch
Debugging      | Hard             | Easy

Real World Use Cases

API Calls

async function getUser() {
  const res = await fetch("https://api.example.com/user");
  const data = await res.json();
  console.log(data);
}

Sequential Task

async function process() {
  const step1 = await task1();
  const step2 = await task2(step1);
  const step3 = await task3(step2);
}

Common Mistakes

Forgetting await

const data = fetchData(); // returns promise

Using await outside async

await fetchData(); // ❌ Error

Mental Model

async → wraps function in promise
await → unwraps promise result

Why This Matters

  • Cleaner Code

  • Better debugging

  • Easier async logic

  • Industry standard