When using for await...of
to iterate over an async generator, the final value (return
value) seems to be consumed and inaccessible afterward. Here’s a minimal example:
async function* exampleGenerator() {
let i = 1;
while (true) {
if (something) {
return 'finished';
}
yield i++;
}
}
async function main() {
const generator = exampleGenerator();
for await (const value of generator) {
console.log(value); // Logs 1, 2, 3...
}
const final = await generator.next();
console.log(final.value); // undefined, expected 'finished'
}
main();
How can I access the final value ('finished'
) after using for await...of
?
Is there a way to retrieve it while keeping the simplicity of the for
loop?
2
Answers
In short, you can’t use a
for ... of
loop if you need the return value of the iterator. A for loop will, as you described, "consume" it.You can change your looping strategy to call the iterator directly:
Explanation
A generator function returns an object that adheres to the iterator protocol. Here’s the relevant bit from the MDN documentation:
A
for ... of
loop exits as soon asdone
istrue
:So your final value is included in the final response from your generator function, but is ignored by the for loop. Calling
next()
again will returnundefined
for the value because the generator has already finished.You can write a little helper
withReturn
that includes thereturn
value –If more
yield
statements occur after thereturn
, they will not be included –Here’s the
async..await
version –Note, if
mygen
does not have areturn
value, anundefined
will be yielded –If this behavior is undesirable, you can conditionally
yield
the return value, if it is present –