Difficulty: Advanced
What are async iterators and async generators in JavaScript? When would you use them?
An async iterator implements the async iterator protocol: each call to next() returns a Promise that resolves to { value, done }.
for await...of loops consume async iterables, awaiting each item.
Async generators (async function*) combine generators and async/await - they can use both yield and await.
Use cases: - Streaming API responses chunk by chunk - Paginated API calls (fetch all pages lazily) - Processing large files line by line - Rate-limited API calls with built-in pausing
async function* fetchPaginatedUsers(baseUrl) {
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(`${baseUrl}?page=${page}`);
const data = await response.json();
yield* data.users;
hasMore = data.hasNextPage;
page++;
}
}
async function processAllUsers() {
for await (const user of fetchPaginatedUsers('/api/users')) {
console.log('Processing:', user.name);
if (user.name === 'Stop') break;
}
}
const asyncRange = {
from: 1, to: 5,
[Symbol.asyncIterator]() {
let current = this.from;
const last = this.to;
return {
async next() {
await new Promise(r => setTimeout(r, 100));
return current <= last
? { value: current++, done: false }
: { done: true };
}
};
}
};
(async () => {
const nums = [];
for await (const num of asyncRange) nums.push(num);
console.log(nums);
})();
Async generators pause between yields, awaiting network calls. Break early stops fetching further pages - lazy evaluation.
async function* streamText(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { done, value } = await reader.read();
if (done) return;
yield decoder.decode(value, { stream: true });
}
} finally {
reader.releaseLock();
}
}
async function processStream() {
let totalChars = 0;
for await (const chunk of streamText('/api/large-file.txt')) {
totalChars += chunk.length;
}
console.log(`Processed ${totalChars} characters`);
}
async function toArray(asyncIter) {
const arr = [];
for await (const item of asyncIter) arr.push(item);
return arr;
}
ReadableStream from fetch is an async iterable. Async generators elegantly wrap streaming APIs.
Async Iterator, for await...of, Async Generator, Streaming