Suggest an editImprove this articleRefine the answer for “What is async/await in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**async/await** is JavaScript syntax for working with Promises without chaining `.then()` calls, making asynchronous code read sequentially. ```javascript async function getUser(id) { const res = await fetch(`/api/users/${id}`); return await res.json(); } ``` **Key:** `async` functions always return a Promise. `await` pauses only that function - the main thread keeps running.Shown above the full answer for quick recall.Answer (EN)Image**async/await** is syntactic sugar over Promises, introduced in ES2017, that lets you write asynchronous JavaScript code in a linear, top-to-bottom style by pausing execution inside an `async` function until a Promise settles. ## Theory ### TL;DR - `async` marks a function as asynchronous and wraps its return value in a Promise automatically - `await` pauses only that specific `async` function until the Promise settles, without blocking the main thread - Analogy: ordering coffee at a busy cafe - you step aside (await pauses your function), the line keeps moving (event loop runs other code), you pick up when ready (Promise resolves) - Use async/await for 2+ sequential async operations; plain Promises for simple one-shot cases - Error handling: `try/catch` replaces `.catch()` chains ### Quick example ```javascript // Promise chain - reads inside-out fetch('/api/user') .then(res => res.json()) .then(user => console.log(user.name)) .catch(err => console.error(err)); // async/await - reads top-to-bottom async function getUser() { try { const res = await fetch('/api/user'); const user = await res.json(); console.log(user.name); // "Alice" } catch (err) { console.error(err); } } ``` Both do the same thing. The async/await version reads in the order things actually happen. ### Key difference `await` transforms a Promise into an assignable value, suspending the `async` function at that line until the Promise settles. The [event loop](/questions/event-loop-in-javascript) keeps running during that pause: other code, timers, and event handlers all continue. When the Promise resolves, the engine enqueues the function's continuation as a microtask, and execution picks up right where it left off. ### When to use - Sequential API calls (fetch a user, then fetch their posts): async/await reads naturally - Error handling across multiple steps: one `try/catch` covers all `await` calls in the block - Parallel operations: use `Promise.all()` inside an `async` function - Single fire-and-forget: a plain [Promise](/questions/what-is-promise-in-javascript) with `.then()` works fine - Legacy code or libraries without Promise support: callbacks or Promises directly ### How the engine handles this V8 compiles `async` functions into state machines using generators internally. Each `await` yields control back to the event loop via `Generator.prototype.next()`. When the awaited Promise settles, the continuation is queued as a microtask, which runs before macrotasks like `setTimeout`. This means code after `await` always runs before pending timer callbacks - something that matters when debugging execution order in tests. ### Common mistakes **Forgetting `await` on a Promise** ```javascript async function bad() { const data = fetch('/api/user'); // Missing await! console.log(data); // Promise { <pending> } } ``` The function continues immediately. `data` holds a Promise object, not the response. Fix: add `await` before `fetch`. **Throwing without handling the returned Promise** ```javascript async function risky() { throw new Error('boom'); // Becomes a rejected Promise } risky(); // Unhandled rejection - crashes Node.js ``` The error doesn't bubble up synchronously. It rejects the Promise that `risky()` returns. Add `.catch()` on the call or `await` it inside a `try/catch`. **`await` outside an `async` function** ```javascript function wrong() { const data = await fetch('/api'); // SyntaxError } ``` `await` only works inside `async` functions (or at the top level of ES modules). Mark the function `async` to fix it. **Assuming `await` blocks the whole program** ```javascript async function a() { await delay(1000); console.log('A'); } async function b() { console.log('B'); } a(); b(); // Output: "B", then "A" ``` `await` pauses only that `async` function. Everything else keeps running. This is the most common wrong answer in interviews when asked about execution order. **Sequential awaits when parallel is faster** ```javascript // Slow: each request waits for the previous to finish const user = await fetchUser(id); const posts = await fetchPosts(id); // Fast: both start at the same time const [user, posts] = await Promise.all([fetchUser(id), fetchPosts(id)]); ``` If two operations don't depend on each other, there is no reason to run them one after another. In code reviews, this is the pattern I see most often. And it's an easy fix. ### Real-world usage - React/Next.js: `const data = await fetchUser(id)` inside Server Components or `getServerSideProps` - Express: `const user = await db.query('SELECT * FROM users WHERE id = ?', [id])` in route handlers - Node.js: `const file = await fs.readFile('data.txt', 'utf8')` with the `fs/promises` module - Axios: `const res = await axios.get('/api/posts')` in Vue or Nuxt apps - Puppeteer: `await page.goto(url)` for browser automation scripts ### Follow-up questions **Q:** What does an `async` function return if you write `return 42`? **A:** Always a Promise. The engine wraps the value via `Promise.resolve(42)`. You get `42` only when you `await` the call or use `.then()`. **Q:** Can you `await` a non-Promise value like a number? **A:** Yes. `await 42` resolves immediately to `42`. Technically the engine wraps it in `Promise.resolve()` first. It works but rarely makes sense outside generic utilities. **Q:** How does `await` handle Promise rejection? **A:** It throws the rejection reason into the `async` function as if it were a synchronous error. A surrounding `try/catch` catches it. **Q:** How do you cancel an awaited operation? **A:** Promises themselves cannot be cancelled, but `fetch` accepts an `AbortController` signal. Pass `{ signal: ac.signal }` to the request and call `ac.abort()` when needed. **Q:** What is the difference between microtasks and macrotasks in the context of `await`? (senior level) **A:** `await` continuations queue as microtasks. Microtasks run after the current synchronous code finishes, before macrotasks like `setTimeout`. So code after `await somePromise` runs before any pending `setTimeout(fn, 0)` callbacks. This ordering is why React Concurrent mode can rely on `await` for precise scheduling. ## Examples ### Basic: what async returns ```javascript async function add(a, b) { return a + b; // Automatically wrapped in Promise.resolve() } // You need .then() or await to get the value add(2, 3).then(result => console.log(result)); // 5 ``` `async` wraps any returned value in a Promise. Even simple arithmetic. You don't get the number directly - you get it through the Promise. ### Intermediate: Express login endpoint ```javascript app.post('/login', async (req, res) => { try { const { email, password } = req.body; const user = await User.findOne({ email }); // DB query if (!user || !await bcrypt.compare(password, user.hash)) { return res.status(401).json({ error: 'Invalid credentials' }); } const token = jwt.sign({ id: user.id }, process.env.SECRET); res.json({ token }); } catch (err) { res.status(500).json({ error: 'Server error' }); } }); // Success: { token: "eyJ..." } // Auth fail: 401 { error: "Invalid credentials" } ``` Two sequential async operations - DB lookup and password comparison - each line waits for the previous. One `try/catch` handles both. This is what async/await looks like in production Node.js code. ### Advanced: race conditions with concurrent async operations ```javascript // Looks safe but isn't: async function tricky() { let x = 0; const p1 = (async () => { await null; x = 1; })(); const p2 = (async () => { await null; x = 2; })(); await Promise.all([p1, p2]); console.log(x); // 1 or 2 - non-deterministic } // Safe pattern for parallel fetches: async function loadDashboard(userId) { const [user, posts, notifications] = await Promise.all([ fetchUser(userId), fetchPosts(userId), fetchNotifications(userId) ]); return { user, posts, notifications }; } ``` `Promise.all()` runs all three in parallel and returns results in the original array order, regardless of which resolves first. The `tricky()` function above is a real race condition: both IIFEs write to `x` after one microtask tick and the order is non-deterministic. Avoid shared mutable state across concurrent async operations.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.