Question presented to candidate: "Say you are calling a paginated API that returns a page of items plus a cursor for the next page. Write an async generator function that streams every item across every page to the caller one at a time, so the caller can use for await...of and start processing before every page has loaded. How do you prove this is actually lazy, one page at a time, and not secretly loading everything up front?"
What a strong answer should cover:
async function*combines a generator (pausable, resumable via yield) with an async function (can await inside), which is exactly the shape needed to await a network call between yields.- The generator holds a loop: await the current page, yield each of its items one at a time, then move to the next page using the cursor the API handed back, stopping when there is no next page.
for await...ofon the consuming side automatically calls the async generator's.next()repeatedly, awaiting each result, and unwraps{ value, done }for you — no manual iterator-protocol code needed.- Laziness is the key selling point over "fetch everything into an array first": only one page fetch is ever in flight at a time, and the NEXT page is not requested until the CURRENT page's items have all been consumed.
- Breaking out of the
for await...ofloop early (abreak, areturn, or an uncaught error) triggers the generator's implicit cleanup and genuinely stops it from fetching any further pages. - This is testable, not just assertable — instrument the fetch function with timestamps or a counter and show the real call pattern rather than describing it from memory.
Clarifying questions expected:
- "Should errors from a single page fetch stop the whole stream, or should the consumer be able to catch and continue?" — a real async generator propagates a thrown error out of the current
for awaititeration, ending the loop, unless the generator body itself catches it. - "Does the API give a full cursor, or just a page number, and can pages be fetched out of order?" — determines whether the loop can be parallelized at all, or whether it is fundamentally sequential.
Code / implementation expected: Yes — a full, runnable async generator plus a real, timestamped test proving only one page fetch is ever in flight, and that an early break genuinely stops further fetching.