What Are Async Generators in JavaScript?
Learn what async generators are, how await and yield combine, and how to stream data with for await...of in JavaScript.
Expected Interview Answer
An async generator is a function declared with `async function*` that can both `await` promises internally and `yield` a sequence of values over time, and is consumed with `for await...of` to pull results one at a time as they become ready.
A regular generator yields synchronous values lazily and is paused/resumed with `.next()`. A regular async function returns a single eventual promise. An async generator combines both: each call to its `.next()` returns a promise that resolves to `{ value, done }`, so the function body can `await` a fetch or database read between each `yield` without blocking the rest of the program. This makes async generators the natural tool for streaming data sources β paginated APIs, readable streams, or WebSocket messages β where you want to process each chunk as it arrives instead of buffering everything into memory first. Consumers use `for await (const item of asyncGen())`, which automatically awaits each `.next()` promise and unwraps `.value`, backpressure-style, so the loop body runs once per item rather than once the whole collection is ready.
- Streams items one at a time instead of buffering the full result set in memory
- Lets you `await` inside the same function that `yield`s, unifying async and lazy iteration
- Composable with `for await...of` for clean, readable consumer code
- Naturally models paginated APIs and chunked streams without manual state machines
AI Mentor Explanation
An async generator is like a ball-by-ball radio commentator who does not read out the whole innings scorecard at once. After each ball is bowled, the commentator waits for the umpireβs signal, then reports that single delivery before waiting again. Listeners hear one ball at a time as it genuinely happens, rather than getting the entire over dumped on them after a long silence. That wait-then-report-one-item loop is exactly the await-then-yield cycle inside an async generator.
Step-by-Step Explanation
Step 1
Declare with async function*
The function combines the async keyword (enables await) with the generator star (enables yield).
Step 2
Await inside the body
Between yields, the function can await promises like fetch calls or database reads.
Step 3
Yield resolves the next() promise
Each yield produces a promise resolving to { value, done: false } for the consumer.
Step 4
Consume with for await...of
The loop automatically awaits each next() call and unwraps value, running once per emitted item.
What Interviewer Expects
- Clear distinction between generators, async functions, and async generators
- Understanding of the { value, done } promise contract returned by next()
- Ability to explain a real streaming use case (pagination, readable streams)
- Awareness of for await...of as the standard consumption pattern
Common Mistakes
- Confusing async generators with plain async functions that just return arrays
- Forgetting that next() itself returns a promise, not a synchronous value
- Not knowing for await...of is required (plain for...of fails on a promise-yielding iterator)
- Buffering all results into an array anyway, defeating the streaming benefit
Best Answer (HR Friendly)
βAn async generator is a special kind of function that can pause on asynchronous work, like a network call, and hand back results one piece at a time as they become ready, instead of making you wait for everything to finish before you see anything. It is great for things like loading a long list of results page by page.β
Code Example
async function* fetchAllUsers(baseUrl) {
let page = 1
while (true) {
const res = await fetch(`${baseUrl}?page=${page}`)
const { users, hasMore } = await res.json()
for (const user of users) {
yield user // one item at a time, not the whole page array
}
if (!hasMore) return
page += 1
}
}
async function printUsers() {
for await (const user of fetchAllUsers('/api/users')) {
console.log(user.name) // runs as each user arrives
}
}Follow-up Questions
- How does an async generator differ from returning an array of promises?
- How would you cancel or break out of a for await...of loop early?
- How do async generators relate to Node.js Readable streams?
- What happens if you call .throw() on an async generator?
MCQ Practice
1. What does async function* combine?
An async generator merges async/await with generator-style lazy yielding.
2. What does calling .next() on an async generator return?
Every next() call returns a promise, since the generator body may need to await internally.
3. What is the correct way to consume an async generator?
for await...of automatically awaits each next() promise and unwraps its value.
Flash Cards
Syntax for an async generator? β async function* name() { ... }
What does next() return on an async generator? β A promise resolving to { value, done }.
How do you consume one? β for await (const item of asyncGen()) { ... }
Best use case? β Streaming paginated or chunked data without buffering it all in memory.