JavaScript Tutorial

Understanding Async/Await in JavaScript

By JobQNA Team • Updated: Jan 12, 2025

Asynchronous programming is the backbone of modern web development. If you've ever fetched data from an API, you know how messy Promises and Callbacks can get. Enter Async/Await—a cleaner, more readable way to handle async operations.

In this guide, we'll break down how Async/Await works, how to handle errors, and why interviewers love asking about it.


1. The Problem with Promises

Before Async/Await (introduced in ES2017), we used .then() chains to handle asynchronous tasks. While better than "Callback Hell," it can still look messy:

// Old way using Promises
fetch('https://api.user.com')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

2. The Solution: Async/Await

async and await are simply "syntactic sugar" built on top of Promises. They make your asynchronous code look and behave like synchronous code (reading from top to bottom).

The `async` Keyword

Placing the keyword async before a function means that function will always return a Promise.

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

// Is the same as:
greet().then(console.log); // Output: Hello!

The `await` Keyword

The keyword await can only be used inside an async function. It pauses the execution of the function until the Promise is resolved.

async function getUser() {
  // Code pauses here until fetch is done
  let response = await fetch('https://api.github.com/users/jobqna');
  let data = await response.json();

  console.log(data);
}

3. Handling Errors (Try/Catch)

In standard Promises, we use .catch(). With Async/Await, we use the standard Javascript try...catch block. This is much more intuitive for developers coming from languages like Java or Python.

async function fetchData() {
  try {
    let res = await fetch('/broken-url');
    let data = await res.json();
    console.log(data);
  } catch (error) {
    // Handles network errors or JSON parsing errors
    console.error("Something went wrong:", error);
  }
}

4. Interview Question: Parallel vs Sequential

A common interview mistake is using await in a loop sequentially when tasks could be done in parallel. This kills performance.

// ❌ SLOW: Waits for user1, then user2
const user1 = await fetch('/user/1');
const user2 = await fetch('/user/2');

// ✅ FAST: Fetches both at the same time
const [user1, user2] = await Promise.all([
  fetch('/user/1'),
  fetch('/user/2')
]);
Cheat Sheet: Need to recall Array methods quickly? Check our JavaScript Cheat Sheet.

Conclusion

Async/Await makes asynchronous code cleaner, easier to debug, and simpler to read. Remember to always wrap your await calls in a try/catch block to handle errors gracefully.