JavaScript Async/Await

Write asynchronous code that looks synchronous

⚑ What is Async/Await?

Async/Await is a syntax that makes it easier to work with Promises. It allows you to write asynchronous code that looks and behaves like synchronous code.


// Without async/await (using promises)
function fetchData() {
    return fetch('/api/data')
        .then(response => response.json())
        .then(data => console.log(data));
}

// With async/await (cleaner!)
async function fetchData() {
    const response = await fetch('/api/data');
    const data = await response.json();
    console.log(data);
}
                                    

Key Concepts

πŸ”„

async

Makes a function return a Promise

async function myFunction() {
    return 'Hello';
}
⏸️

await

Pauses function until Promise resolves

const result = await promise;
🎯

Error Handling

Use try/catch for errors

try {
    await promise;
} catch (error) {
    console.log(error);
}
πŸ“

Clean Code

No more callback hell

// Readable and clean
const data = await getData();

πŸ”Ή Basic Async/Await

Here's how to use async/await:

// Creating an async function
async function greetUser() {
    return 'Hello, User!';
}

// Calling async function
greetUser().then(message => console.log(message));

// Or using await (inside another async function)
async function main() {
    const greeting = await greetUser();
    console.log(greeting);
}

main();

// Async function with delay
async function delayedMessage() {
    // Create a promise that resolves after 2 seconds
    const delay = new Promise(resolve => {
        setTimeout(() => resolve('Message after delay!'), 2000);
    });
    
    console.log('Waiting...');
    const message = await delay;
    console.log(message);
}

delayedMessage();

Output:

Hello, User!

Hello, User!

Waiting...

(After 2 seconds...) Message after delay!

πŸ”Ή Error Handling

Use try/catch blocks to handle errors in async functions:

// Function that might fail
async function riskyOperation() {
    const random = Math.random();
    if (random > 0.5) {
        return 'Success!';
    } else {
        throw new Error('Operation failed!');
    }
}

// Handling errors with try/catch
async function handleRiskyOperation() {
    try {
        const result = await riskyOperation();
        console.log('Result:', result);
    } catch (error) {
        console.log('Error caught:', error.message);
    } finally {
        console.log('Operation completed');
    }
}

handleRiskyOperation();

// Multiple operations with error handling
async function multipleOperations() {
    try {
        const result1 = await riskyOperation();
        console.log('First operation:', result1);
        
        const result2 = await riskyOperation();
        console.log('Second operation:', result2);
        
    } catch (error) {
        console.log('One of the operations failed:', error.message);
    }
}

multipleOperations();

Output (example):

Result: Success!

Operation completed

First operation: Success!

One of the operations failed: Operation failed!

πŸ”Ή Real-World Example

Here's a practical example of fetching user data:

// Simulating API calls
function fetchUser(id) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (id > 0) {
                resolve({ id: id, name: 'John Doe', email: '[email protected]' });
            } else {
                reject(new Error('Invalid user ID'));
            }
        }, 1000);
    });
}

function fetchUserPosts(userId) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve([
                { id: 1, title: 'First Post', content: 'Hello World!' },
                { id: 2, title: 'Second Post', content: 'Learning JavaScript!' }
            ]);
        }, 1500);
    });
}

// Using async/await to fetch user and their posts
async function getUserData(userId) {
    try {
        console.log('Fetching user data...');
        const user = await fetchUser(userId);
        console.log('User found:', user.name);
        
        console.log('Fetching user posts...');
        const posts = await fetchUserPosts(user.id);
        console.log('Posts found:', posts.length);
        
        return {
            user: user,
            posts: posts
        };
        
    } catch (error) {
        console.log('Error:', error.message);
        return null;
    }
}

// Using the function
async function displayUserProfile() {
    const userData = await getUserData(123);
    if (userData) {
        console.log('Profile loaded successfully!');
        console.log('User:', userData.user.name);
        console.log('Posts:', userData.posts.map(p => p.title));
    }
}

displayUserProfile();

Output:

Fetching user data...

(After 1 second...) User found: John Doe

Fetching user posts...

(After 2.5 seconds...) Posts found: 2

Profile loaded successfully!

User: John Doe

Posts: ["First Post", "Second Post"]

πŸ”Ή Parallel vs Sequential

Control how async operations run:

// Sequential (one after another)
async function sequential() {
    console.log('Sequential start');
    const start = Date.now();
    
    const result1 = await delay(1000, 'First');
    const result2 = await delay(1000, 'Second');
    const result3 = await delay(1000, 'Third');
    
    const end = Date.now();
    console.log('Sequential results:', [result1, result2, result3]);
    console.log('Sequential time:', end - start, 'ms');
}

// Parallel (all at once)
async function parallel() {
    console.log('Parallel start');
    const start = Date.now();
    
    const [result1, result2, result3] = await Promise.all([
        delay(1000, 'First'),
        delay(1000, 'Second'),
        delay(1000, 'Third')
    ]);
    
    const end = Date.now();
    console.log('Parallel results:', [result1, result2, result3]);
    console.log('Parallel time:', end - start, 'ms');
}

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

// Run both examples
async function compare() {
    await sequential(); // Takes ~3 seconds
    await parallel();   // Takes ~1 second
}

compare();

Output:

Sequential start

(After 3 seconds...) Sequential results: ["First", "Second", "Third"]

Sequential time: 3003 ms

Parallel start

(After 1 second...) Parallel results: ["First", "Second", "Third"]

Parallel time: 1002 ms

🧠 Test Your Knowledge

What keyword do you use to wait for a Promise to resolve?