Skip to main content

Command Palette

Search for a command to run...

Async/Await in JavaScript

Writing Cleaner Asynchronous Code

Updated
•View as Markdown
Async/Await in JavaScript

In the previous blog, you learned how promises help manage asynchronous operations in a cleaner way compared to callbacks.

Promises improved readability, but they still have a limitation.

When multiple asynchronous steps are chained together, the code can still become difficult to follow.

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

This is better than callbacks, but it still feels like a chain rather than a natural flow.

This is exactly why async and await were introduced.


Why Async/Await Was Introduced

Async/await was introduced to make asynchronous code look and behave more like synchronous code.

The goal is simple.

Write asynchronous logic in a way that is easy to read, easy to understand, and easy to maintain.

Instead of chaining .then(), you write code step by step.


What is an Async Function?

An async function is a function that always returns a promise.

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

Even though it returns a simple value, JavaScript wraps it in a promise.

So internally, it behaves like:

Promise.resolve("Hello");

The Await Keyword

The await keyword is used inside async functions.

It pauses the execution of the function until the promise is resolved.

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

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

getData();

Here, await makes the code look synchronous.

Instead of using .then(), you directly assign the result to a variable.


How This Improves Readability

Compare both approaches.

Using Promises

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

Using Async/Await

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

The second version reads like a normal flow.

This makes complex logic much easier to understand.


Error Handling with Async/Await

Handling errors with promises requires .catch().

With async/await, you can use try...catch.

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

This looks cleaner and more structured.


Async/Await is Syntactic Sugar

Async/await is not a replacement for promises.

It is built on top of promises.

You can think of it as a simpler way to write promise-based code.

Under the hood, everything still uses promises.


Execution Flow

Even though await looks like it pauses execution, JavaScript is still non-blocking.

Only the async function waits.

The rest of the program continues to run.


Real-World Example

function fetchUser() {
  return new Promise(resolve => {
    setTimeout(() => resolve("User data"), 2000);
  });
}

function fetchPosts() {
  return new Promise(resolve => {
    setTimeout(() => resolve("User posts"), 2000);
  });
}

async function getUserDetails() {
  const user = await fetchUser();
  const posts = await fetchPosts();

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

getUserDetails();

This is how real applications fetch and process data step by step.


Promise vs Async/Await

Promises:
.then().then().then()

Async/Await:
step → step → step

Async/await removes chaining and makes code more readable.


Common Mistakes

One common mistake is using await outside an async function.

Another is forgetting that async functions always return promises.

Also, writing sequential await calls when they could run in parallel can slow down performance.


Final Thought

Async/await makes asynchronous code feel natural.

Instead of thinking in terms of callbacks or chains, you start writing code in a simple, step-by-step flow.

It improves readability without changing how JavaScript works underneath.

Once you get comfortable with async/await, writing asynchronous code becomes much easier and more intuitive.

Asynchronous JavaScript ( Async JS Explained )

Part 3 of 4

Asynchronous JavaScript is a beginner-friendly series designed to help you understand how JavaScript handles tasks that don’t run immediately. From callbacks to promises and async/await, this series breaks down asynchronous behavior into simple, real-world examples so you can write efficient, non-blocking, and modern JavaScript code with confidence.

Up next

Error Handling in JavaScript

Try, Catch, Finally