JavaScript Async/Await — Complete Guide for Beginners

Learn how to handle asynchronous JavaScript with async/await, error handling, parallel execution, and real-world patterns.

JavaScript Intermediate 📖 10 min

What Is Async/Await?

async/await is syntactic sugar built on top of Promises. It lets you write asynchronous code that looks and behaves like synchronous code, making it far easier to read and debug.

Basic Syntax

An async function always returns a Promise. The await keyword pauses execution until the Promise resolves.

async function fetchUser() {
  const response = await fetch('https://api.example.com/user/1');
  const user = await response.json();
  return user;
}

// Calling the async function
fetchUser().then(user => console.log(user));

Error Handling with try/catch

Always wrap await calls in try/catch blocks to handle rejections gracefully.

async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Failed to fetch data:', error.message);
    return { error: true, message: error.message };
  }
}

Parallel Execution

Avoid sequential awaits when requests are independent — use Promise.all() instead.

// BAD: Sequential (slower)
async function getSequential() {
  const users = await fetch('/api/users').then(r => r.json());
  const posts = await fetch('/api/posts').then(r => r.json());
  const comments = await fetch('/api/comments').then(r => r.json());
  return { users, posts, comments };
}

// GOOD: Parallel (faster)
async function getParallel() {
  const [users, posts, comments] = await Promise.all([
    fetch('/api/users').then(r => r.json()),
    fetch('/api/posts').then(r => r.json()),
    fetch('/api/comments').then(r => r.json())
  ]);
  return { users, posts, comments };
}

Promise.allSettled for Partial Success

When you want all results regardless of failures, use Promise.allSettled().

async function fetchMultiple() {
  const results = await Promise.allSettled([
    fetch('/api/users'),
    fetch('/api/posts'),
    fetch('/api/comments')
  ]);
  results.forEach((result, index) => {
    if (result.status === 'fulfilled') {
      console.log(`Request ${index} succeeded:`, result.value);
    } else {
      console.log(`Request ${index} failed:`, result.reason);
    }
  });
}

Retry with Exponential Backoff

async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
    }
  }
}

Top-Level Await

In ES modules, you can use await at the top level without wrapping in an async function.

// module.js
const response = await fetch('/api/config');
const config = await response.json();
export default config;

Ready to Level Up Your Coding Skills?

Join Coderz Club and learn to code with challenges, battles, and an AI mentor.

Join Coderz Club Free →