Async Generators & For-Await-Of0%

Async Generators & For-Await-Of

Beginner12 min read•Updated: Jul 11, 2026
Study Materials

Async Generators & For-Await-Of in Modern JavaScript

While standard generator functions (function*) produce synchronous sequences, modern applications frequently stream asynchronous data chunks—such as real-time WebSocket messages, chunked HTTP response bodies, database cursor pages, and file streams. Async Generators (async function*) and the for await...of loop provide first-class language support for asynchronous iteration.


1. Defining an Async Generator: async function*

An async generator function combines async with function*:

  • Each yield expression can emit a value or a Promise.
  • Calling .next() returns a Promise that resolves to { value, done }.
JavaScript
async function* fetchUserPages(totalPages) {
for (let page = 1; page <= totalPages; page++) {
console.log(`[Network] Fetching page ${page}...`);
// Await API response inside generator
const response = await fetch(`https://jsonplaceholder.typicode.com/users?_page=${page}&_limit=2`);
const users = await response.json();
 
yield users; // Emits page data asynchronously
}
}

2. Consuming Streams with for await...of

The for await...of loop pauses at each iteration until the promise yielded by the async iterator settles:

JavaScript
async function processAllPages() {
const pageStream = fetchUserPages(3);
 
// Iterates over each asynchronous batch smoothly!
for await (const userBatch of pageStream) {
console.log(`Received batch of ${userBatch.length} users:`);
userBatch.forEach(u => console.log(` - ${u.name}`));
}
 
console.log('All user pages processed successfully!');
}
 
processAllPages();
Output
Async Stream Execution:
for await...of
│
├──► Awaits page 1 ──► [ Yields 2 Users ] ──► Loop body runs
├──► Awaits page 2 ──► [ Yields 2 Users ] ──► Loop body runs
├──► Awaits page 3 ──► [ Yields 2 Users ] ──► Loop body runs
└──► done: true ──► Loop finishes

3. Streaming Large Files with ReadableStream

Modern browsers and Node.js expose ReadableStream on fetch responses. Async iteration enables stream processing without loading gigabyte-sized files into RAM:

JavaScript
async function readTextStream(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
 
try {
while (true) {
const { value, done } = await reader.read();
if (done) break;
 
const textChunk = decoder.decode(value, { stream: true });
console.log('Received Chunk:', textChunk.length, 'bytes');
}
} finally {
reader.releaseLock();
}
}

4. Backpressure Management

A major advantage of for await...of is automatic backpressure: If processing a chunk takes 500ms, the loop will not request the next chunk from the generator until the current loop iteration finishes, preventing memory overflow.


Interactive Quiz

Practice Quiz

Question 1
What does invoking an async generator function (async function*()) return?
Question 2
What loop statement is designed to consume AsyncIterables in modern JavaScript?
Question 3
What is "backpressure" and how does for await...of assist in managing it?
Question 4
Can you use the await keyword inside an async function* generator?
Question 5
What does iterator.next() return when called on an async iterator?
Next Lesson

Web Workers & Multithreading in JS

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext