Async generators produce values over time, and `for await...of` consumes them one at a time, awaiting each. Readable streams are themselves async iterable, which is often cleaner than juggling `"data"`/`"end"` event listeners.
js
async function* paginate(fetchPage) {
let page = 1;
while (true) {
const items = await fetchPage(page++);
if (items.length === 0) return;
yield* items;
}
}
for await (const item of paginate(fetchTransactionsPage)) {
console.log(item.hash);
}
// a Readable stream is also async-iterable:
for await (const chunk of createReadStream("./data.csv")) {
process(chunk);
}This pattern shines for paginated blockchain indexer APIs, where you want to process an unbounded sequence of results without loading them all into memory up front.