Async/Await
Async/Await
Section titled โAsync/AwaitโWhat it is
Section titled โWhat it isโAsync/await provides a more synchronous-looking syntax for working with Promises. Introduced in ES2017 (ES8), it makes asynchronous code look and behave more like synchronous code.
Before this feature
Section titled โBefore this featureโPromise chains could still become unwieldy:
function getUser() { return fetch("/api/user") .then(response => response.json()) .then(user => { return fetch(`/api/posts/${user.id}`) .then(response => response.json()) .then(posts => { return { user, posts }; }); }) .catch(err => console.error(err));}After this feature
Section titled โAfter this featureโAsync/await makes it linear and readable:
async function getUser() { try { const response = await fetch("/api/user"); const user = await response.json();
const postsResponse = await fetch(`/api/posts/${user.id}`); const posts = await postsResponse.json();
return { user, posts }; } catch (err) { console.error(err); }}
// Arrow function versionconst getUserData = async (id) => { const response = await fetch(`/api/users/${id}`); return await response.json();};
// Top-level await (ES2022 - in modules)const data = await fetch("/api/config").then(r => r.json());
// Parallel executionasync function getMultiple() { // Sequential (slow) const user = await fetchUser(); const posts = await fetchPosts();
// Parallel (fast) const [user2, posts2] = await Promise.all([ fetchUser(), fetchPosts() ]);
return { user2, posts2 };}Why this is better
Section titled โWhy this is betterโ- Readable: Looks like synchronous code
- Error handling: Use familiar try/catch
- Debugging: Easier to set breakpoints and step through
- Less nesting: Avoids callback/promise chain indentation
- Intuitive: Easier for developers new to async programming
Key notes / edge cases
Section titled โKey notes / edge casesโasyncfunctions always return a Promiseawaitcan only be used insideasyncfunctions (except top-level in modules)- Forgetting
awaitis a common mistake (you get a Promise instead of the value) - Sequential awaits can be slow; use
Promise.all()for parallel operations - Error in await without try/catch creates unhandled promise rejection
awaitpauses function execution but doesnโt block the event loop
// Common mistake: sequential when parallel would workasync function slow() { const a = await fetch("/api/a"); // waits 1s const b = await fetch("/api/b"); // waits 1s // Total: 2s}
async function fast() { const [a, b] = await Promise.all([ fetch("/api/a"), fetch("/api/b") ]); // Total: 1s (parallel)}Quick practice
Section titled โQuick practiceโ-
Convert this to async/await:
fetch('/api/user').then(r => r.json()).then(user => console.log(user))Answer
async function getUser() {const response = await fetch('/api/user');const user = await response.json();console.log(user);} -
What does an
asyncfunction return?Answer
Always returns a Promise. If you return a value, it's wrapped in `Promise.resolve(value)`. -
How do you run three async operations in parallel and wait for all?
Answer
const [a, b, c] = await Promise.all([fetchA(),fetchB(),fetchC()]);