JavaScript Internals (521 Qs)•Part 8: Modern JavaScript APIs, WeakRef, Proxy & Performance (464 - 521)
What are async iterators and how are they different from regular iterators?
Async iterators allow you to iterate over asynchronous data sources using for await...of loops, where each iteration can wait for a Promise to resolve.
Regular iterator (synchronous):
javascript
const syncIterable = {
[Symbol.iterator]() {
let i = 0;
return {
next() {
if (i < 3) {
return { value: i++, done: false };
}
return { done: true };
}
};
}
};
for (const val of syncIterable) {
console.log(val); // 0, 1, 2
}
Async iterator:
javascript
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
async next() {
if (i < 3) {
await new Promise(resolve => setTimeout(resolve, 1000));
return { value: i++, done: false };
}
return { done: true };
}
};
}
};
(async () => {
for await (const val of asyncIterable) {
console.log(val); // 0, 1, 2 (one per second)
}
})();
Async generator function:
javascript
async function* fetchPages(urls) {
for (const url of urls) {
const response = await fetch(url);
const data = await response.json();
yield data;
}
}
(async () => {
const urls = ['api/page1', 'api/page2', 'api/page3'];
for await (const page of fetchPages(urls)) {
console.log(page);
}
})();
Practical example - reading file streams:
javascript
async function* readLines(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
yield line;
}
}
(async () => {
for await (const line of readLines('large-file.txt')) {
console.log(line);
}
})();
Key differences:
| Regular Iterator | Async Iterator |
|---|---|
Returns { value, done } | Returns Promise<{ value, done }> |
Symbol.iterator | Symbol.asyncIterator |
Used with for...of | Used with for await...of |
| Synchronous | Asynchronous |
next() method | async next() method |