Async/Await is a syntactic pattern for writing asynchronous code that looks synchronous. Built on Promises (JS) or Futures (Rust, Python, etc.).


Evolution of Async Patterns

1. Callbacks

Functions passed as arguments, invoked when work completes.

getUserData(123, (userData) => {
    getUserPosts(userData, (posts) => {
        getPostComments(posts[0], (comments) => {
            console.log(comments);  // Callback hell
        });
    });
});

Problems: Callback hell, complex error handling, hard to read.


2. Promises / Futures

Represent a value that will be available in the future.

getUserData(123)
    .then(userData => getUserPosts(userData))
    .then(posts => getPostComments(posts[0]))
    .then(comments => console.log(comments))
    .catch(error => console.error(error));

Better: Chainable, cleaner error handling, avoids deep nesting.


3. Async/Await

Syntactic sugar over Promises — looks synchronous.

async function fetchUserDataAndPosts() {
    try {
        const userData = await getUserData(123);
        const posts = await getUserPosts(userData);
        const comments = await getPostComments(posts[0]);
        console.log(comments);
    } catch (error) {
        console.error(error);
    }
}

Best: Readable, try/catch for errors, sequential flow.


Comparison Across Languages

Language Future Type Await Syntax Runtime
JavaScript Promise await Event loop
Python Future / Coroutine await asyncio
Rust Future .await tokio / async-std
Go Goroutines + channels