How Does async/await Work in JavaScript?
Master JavaScript async/await: how async functions return Promises, how await pauses without blocking, and try/catch error handling with examples.
Expected Interview Answer
async/await is syntactic sugar over Promises that lets you write asynchronous code in a synchronous-looking, top-to-bottom style: an async function always returns a Promise, and await pauses that function until a Promise settles.
Marking a function async makes it return a Promise automatically, wrapping any returned value. Inside it, await unwraps a Promise to its fulfilled value and suspends the function without blocking the main thread — control returns to the event loop until the awaited Promise settles. Errors from rejected Promises surface as thrown exceptions, so you handle them with ordinary try/catch. It is the same Promise machinery underneath, just far more readable than long .then() chains.
- Reads like synchronous, top-to-bottom code
- try/catch handles async errors naturally
- Eliminates deeply nested .then() chains
- Easier to debug with step-through and stack traces
- Interoperates with all existing Promise-based APIs
AI Mentor Explanation
await is like a batter calling for a review and simply waiting at the crease for the verdict before playing on — but crucially the rest of the match (the event loop) keeps ticking around them. The async innings reads ball by ball in order, yet each 'await' pauses only that batter until the third-umpire Promise settles, at which point they resume exactly where they stopped.
Step-by-Step Explanation
Step 1
Mark the function async
Adding async makes the function return a Promise; any returned value is auto-wrapped as a fulfilled Promise.
Step 2
await a Promise
Place await before a Promise-returning expression to suspend the function until that Promise settles.
Step 3
Yield to the event loop
While awaiting, the function is paused and the main thread is free to run other work — nothing blocks.
Step 4
Resume with the value
When the Promise fulfills, await evaluates to its value and execution continues on the next line.
Step 5
Handle errors with try/catch
A rejected awaited Promise throws, so wrap awaits in try/catch to handle failures cleanly.
Step 6
Parallelise when independent
For independent tasks, start them first and await Promise.all instead of awaiting each in sequence.
What Interviewer Expects
- That an async function always returns a Promise
- await pauses the function without blocking the thread
- Error handling via try/catch around await
- Knowing it is sugar over the same Promise machinery
- When to use Promise.all to avoid sequential awaits
Common Mistakes
- Using await inside a normal (non-async) function
- Awaiting independent Promises sequentially, wasting time
- Forgetting try/catch, leaving rejections unhandled
- Thinking await blocks the whole thread rather than just the function
- Using await inside a forEach and expecting it to wait
Best Answer (HR Friendly)
“async/await is a cleaner way to write code that waits for slow tasks like fetching data. You write it top to bottom as if it were normal step-by-step code, and JavaScript handles the waiting behind the scenes without freezing the app.”
Code Example
async function getDashboard() {
try {
// Sequential: each await waits for the previous one
const user = await fetchUser()
const posts = await fetchPosts(user.id)
// Parallel: start both, then await together
const [stats, alerts] = await Promise.all([
fetchStats(user.id),
fetchAlerts(user.id),
])
return { user, posts, stats, alerts }
} catch (err) {
console.error('Dashboard failed:', err.message)
throw err
}
}
getDashboard().then((data) => console.log('Ready', data))Follow-up Questions
- How do you run multiple awaits in parallel?
- What does an async function return if you return a plain value?
- How is error handling different between .catch and try/catch?
- Why doesn't await work as expected inside array.forEach?
- Can top-level await be used in modules?
MCQ Practice
1. What does an async function always return?
An async function always returns a Promise; any value you return is wrapped in a fulfilled Promise, and a thrown error produces a rejected one.
2. What is the effect of await on the main thread?
await suspends just the async function and returns control to the event loop, so other work keeps running; the thread is never blocked.
3. How should you handle a rejected awaited Promise?
A rejected awaited Promise throws an exception, so wrapping the await in try/catch handles the error just like synchronous code.
Flash Cards
What does async do to a function? — It makes the function return a Promise, automatically wrapping returned values and rejected on thrown errors.
What does await do? — It suspends the async function until the awaited Promise settles, then resumes with its fulfilled value — without blocking the thread.
How do you catch async errors? — Wrap the await in try/catch; a rejected Promise throws, so ordinary catch handles it.
Sequential vs parallel awaits? — Awaiting one after another runs them in sequence; use Promise.all on independent tasks to run them concurrently.