How to Use Async/Await in JavaScript | The School of Code

Settings

Appearance

Choose a typography theme that suits your style

Back to How-to Guides
JavaScript

How to Use Async/Await in JavaScript

Learn how to write asynchronous JavaScript code using async/await for cleaner, more readable code.

JavaScriptAsyncAwaitPromisesAsynchronous

Async/await is a modern way to handle asynchronous operations in JavaScript, making code easier to read and write.

Basic Syntax

// Async function declaration
async function fetchData() {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
}

// Calling the async function
fetchData().then(data => console.log(data));

Why Use Async/Await?

Compare with traditional Promise chains:

// Promise chain (harder to read)
function getUserData(userId) {
    return fetch(`/api/users/${userId}`)
        .then(response => response.json())
        .then(user => fetch(`/api/posts/${user.id}`))
        .then(response => response.json())
        .then(posts => ({ user, posts }));
}

// Async/await (cleaner)
async function getUserData(userId) {
    const userResponse = await fetch(`/api/users/${userId}`);
    const user = await userResponse.json();
    
    const postsResponse = await fetch(`/api/posts/${user.id}`);
    const posts = await postsResponse.json();
    
    return { user, posts };
}

Error Handling

Use try/catch for error handling:

async function fetchUser(id) {
    try {
        const response = await fetch(`/api/users/${id}`);
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const user = await response.json();
        return user;
    } catch (error) {
        console.error('Failed to fetch user:', error);
        throw error; // Re-throw if you want calling code to handle it
    }
}

Parallel Execution

Run multiple async operations simultaneously:

async function fetchAllData() {
    // Sequential (slow) - waits for each one
    const users = await fetch('/api/users').then(r => r.json());
    const posts = await fetch('/api/posts').then(r => r.json());
    
    // Parallel (fast) - runs simultaneously
    const [usersData, postsData] = await Promise.all([
        fetch('/api/users').then(r => r.json()),
        fetch('/api/posts').then(r => r.json())
    ]);
    
    return { users: usersData, posts: postsData };
}

Async Arrow Functions

// Arrow function syntax
const fetchData = async () => {
    const response = await fetch('/api/data');
    return response.json();
};

// In array methods
const urls = ['/api/user/1', '/api/user/2', '/api/user/3'];

// Fetch all users in parallel
const users = await Promise.all(
    urls.map(async (url) => {
        const response = await fetch(url);
        return response.json();
    })
);

Async in Loops

Be careful with async in loops:

// Sequential processing
async function processSequentially(items) {
    for (const item of items) {
        await processItem(item);
    }
}

// Parallel processing
async function processInParallel(items) {
    await Promise.all(items.map(item => processItem(item)));
}

// Note: forEach doesn't wait for async!
// This WON'T work as expected:
items.forEach(async (item) => {
    await processItem(item); // Doesn't wait!
});

Using with setTimeout

Create a delay function:

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function fetchWithRetry(url, retries = 3) {
    for (let i = 0; i < retries; i++) {
        try {
            const response = await fetch(url);
            return await response.json();
        } catch (error) {
            if (i < retries - 1) {
                await delay(1000 * (i + 1)); // Exponential backoff
            } else {
                throw error;
            }
        }
    }
}

Top-Level Await

In ES modules, you can use await at the top level:

// In an ES module (.mjs or type="module")
const response = await fetch('/api/config');
const config = await response.json();

export { config };

Summary

  • Use async keyword to define an async function
  • Use await to pause execution until a Promise resolves
  • Wrap in try/catch for error handling
  • Use Promise.all() for parallel execution
  • Be careful with async in loops - prefer for...of over forEach