async/await

📖 Concept

async/await is syntactic sugar over Promises that makes asynchronous code look and behave like synchronous code. It's the modern, preferred way to handle async operations.

async function — Always returns a Promise. If you return a value, it's wrapped in Promise.resolve(). await — Pauses execution of the async function until the Promise resolves. Can only be used inside async functions (or top-level in modules).

🏠 Real-world analogy: async/await is like reading a recipe step by step. "Mix the flour, AWAIT until it's smooth, then add eggs, AWAIT until blended." Each step finishes before the next starts, but the kitchen (event loop) isn't blocked — the chef can check other things while waiting.

💻 Code Example

codeTap to expand ⛶
1// Basic async/await
2async function fetchUser(id) {
3 const response = await fetch(`/api/users/${id}`);
4 const user = await response.json();
5 return user; // Automatically wrapped in Promise.resolve()
6}
7
8// Error handling with try/catch
9async function loadData() {
10 try {
11 const user = await fetchUser(1);
12 const posts = await fetch(`/api/posts?userId=${user.id}`);
13 const data = await posts.json();
14 return { user, posts: data };
15 } catch (error) {
16 console.error("Failed to load:", error.message);
17 throw error; // Re-throw for caller to handle
18 } finally {
19 console.log("Loading complete");
20 }
21}
22
23// Parallel async operations (DON'T await sequentially!)
24// ❌ BAD — sequential (slow!)
25async function fetchSequential() {
26 const users = await fetch("/api/users"); // Wait 1s
27 const posts = await fetch("/api/posts"); // Wait another 1s
28 // Total: 2 seconds
29}
30
31// ✅ GOOD — parallel (fast!)
32async function fetchParallel() {
33 const [users, posts] = await Promise.all([
34 fetch("/api/users"),
35 fetch("/api/posts")
36 ]);
37 // Total: ~1 second (parallel)
38}
39
40// Async iteration
41async function* generatePages(url) {
42 let page = 1;
43 while (true) {
44 const res = await fetch(`${url}?page=${page}`);
45 const data = await res.json();
46 if (data.length === 0) break;
47 yield data;
48 page++;
49 }
50}
51
52// for await...of
53async function getAllPages() {
54 for await (const page of generatePages("/api/items")) {
55 console.log("Page:", page);
56 }
57}
58
59// Top-level await (ES Modules only)
60// const config = await fetch("/config.json").then(r => r.json());
61
62// Async class methods
63class ApiClient {
64 async get(url) {
65 const res = await fetch(url);
66 if (!res.ok) throw new Error(`HTTP ${res.status}`);
67 return res.json();
68 }
69}

🏋️ Practice Exercise

Mini Exercise:

  1. Convert a Promise chain to async/await
  2. Implement parallel data fetching with proper error handling
  3. Write an async function that retries a fetch up to 3 times
  4. Build a simple async queue that processes tasks one at a time

⚠️ Common Mistakes

  • Awaiting in a loop (sequential) when operations are independent — use Promise.all for parallel execution

  • Forgetting try/catch — unhandled rejections in async functions go to .catch() or crash the process

  • Using await at the top level without modules — only works in ES Modules or Chrome DevTools

  • Returning await promise vs return promise — they're almost the same, but return await in try/catch catches the error

  • Forgetting that async functions always return a Promise — even if you return a plain value

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for async/await. Login to unlock this feature.