Skip to main content

Command Palette

Search for a command to run...

Async Await in JavaScript Writing Cleaner Asynchronous Code

Published
3 min read
Async Await in JavaScript Writing Cleaner Asynchronous Code

When we learned about asynchronous JavaScript we saw how callbacks work.

Then promises came to solve callback nesting.

But even promises can feel messy sometimes with .then() chains.

So JavaScript introduced async and await to make things cleaner.

In this blog I will share how I understand async await and why it makes async code easier to read and write.


Why async await was introduced

With promises we usually write code like:

fetchData()
  .then((res) => {
    return processData(res)
  })
  .then((data) => {
    console.log(data)
  })
  .catch((err) => {
    console.log(err)
  })

This works fine.

But as things grow it starts looking like a chain.

Harder to read.

So async await was introduced to make this look like normal code.


How async functions work

When you add async before a function:

async function getData() {
  return "hello"
}

This function always returns a promise.

Even if you return a normal value.

getData().then(console.log) // hello

So:

async function → always returns promise


What await does

await is used inside async function.

It pauses the execution until promise resolves.

Example:

async function getData() {
  const res = await fetch("https://api.freeapi.app/api/v1/public/randomusers?page=1&limit=10")
  console.log(res)
}

Here:

JavaScript waits for fetch to finish then moves to next line

So it feels like synchronous code.


How it actually feels

Instead of:

Promise → then → then

You write:

Step 1 wait Step 2


Promise vs async await

Promise style:

fetchData()
  .then((res) => processData(res))
  .then((data) => console.log(data))

Async await style:

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

Same thing.

But second one looks cleaner.


Async function flow


Error handling with async await

With promises:

fetchData()
  .then((res) => console.log(res))
  .catch((err) => console.log(err))

With async await:

async function run() {
  try {
    const res = await fetchData()
    console.log(res)
  } catch (err) {
    console.log(err)
  }
}

Same concept.

Just cleaner.


Why this matters

Async await makes code:

  • easier to read

  • easier to debug

  • easier to write

It looks like normal step by step code even though it is async.


Important thing to remember

  • await only works inside async function

  • async function always returns promise


Simple real example

async function getUser() {
  try {
    const res = await fetch("https://api.freeapi.app/api/v1/public/randomusers?page=1&limit=10")
    const data = await res.json()
    console.log(data)
  } catch (err) {
    console.log("Error fetching user")
  }
}

Mental model

async await is just:

promise + cleaner syntax

Nothing new under the hood.


Async await does not replace promises.

It is built on top of promises.

It just makes async code look simple and readable.