Navigate
Search topics, hooks, and fundamentals
Async/await makes promise-based code read like synchronous code. Same promises underneath, but much cleaner syntax.
async/await is syntactic sugar over promises. The same logic, but reads top-to-bottom:
// Promise chain
function fetchUserData() {
return fetch("/api/user")
.then(res => res.json())
.then(user => fetch(`/api/orders/${user.id}`))
.then(res => res.json());
}
// Async/await — same logic, reads top-to-bottom
async function fetchUserData() {
const res = await fetch("/api/user");
const user = await res.json();
const ordersRes = await fetch(`/api/orders/${user.id}`);
return ordersRes.json();
}Watch an order flow execute step by step. Each await pauses the function until the promise resolves:
const res = await fetch("/api/user")const user = await res.json()const ordersRes = await fetch(`/api/orders/${user.id}`)const orders = await ordersRes.json()return ordersReplace .catch() with familiar try/catch blocks:
async function placeOrder(item) {
try {
const order = await createOrder(item);
const confirmation = await processPayment(order.id);
return confirmation;
} catch (error) {
// Catches errors from ANY await above
console.error("Order failed:", error.message);
throw error; // re-throw if caller should handle it
} finally {
// Always runs — cleanup logic goes here
hideLoadingSpinner();
}
}When awaits don't depend on each other, run them in parallel with Promise.all — don't make them wait in line:
Sequential (waterfall)
Parallel (Promise.all)
// Sequential — each waits for the previous
const users = await fetchUsers(); // 800ms
const posts = await fetchPosts(); // 600ms
const comments = await fetchComments(); // 400ms
// Total: ~1800ms (waterfall!)
// Parallel — all start at once
const [users, posts, comments] = await Promise.all([
fetchUsers(), // 800ms ─┐
fetchPosts(), // 600ms ├─ ~800ms total
fetchComments(), // 400ms ─┘
]);An async function always returns a Promise. await simply unwraps it:
// async/await is syntactic sugar over promises
// These are IDENTICAL:
// Version 1: Promise
function getUser() {
return fetch("/user").then(r => r.json());
}
// Version 2: async/await
async function getUser() {
const r = await fetch("/user");
return r.json(); // auto-wrapped in a Promise
}
// An async function ALWAYS returns a Promiseasync marks a function as returning a Promiseawait pauses execution until the Promise resolvestry/catch for error handling instead of .catch()