Reputation: 55729
MDN has an example in which a generator function is marked as async
, and yield
is used without await
.
Why is await
not necessary in this example?
const myAsyncIterable = {
async* [Symbol.asyncIterator]() {
yield "hello"
yield "async"
yield "iteration!"
}
}
Upvotes: 0
Views: 743
Reputation: 370769
Just because an function is async
doesn't mean that await
is required. I think this example has async
just to show that you could easily insert an await
ed Promise into it.
Something with a Symbol.asyncIterator
can be iterated over asynchronously if needed, but it doesn't have to have any asynchronous operations. You could even replace the async function with a standard generator function, on the Symbol.asyncIterator
property, and still have things work just fine:
const myAsyncIterable = {
*[Symbol.asyncIterator]() {
yield "hello"
yield "async"
yield "iteration!"
}
};
(async () => {
for await (const item of myAsyncIterable) {
console.log(item);
}
})();
Looking at the specification, after the iterator is retrieved from the object, it doesn't matter whether the iterator is sync or async. An async generator function will result in an async iterator; a sync generator function will result in a sync iterator. See the final step 7 of the spec here - GetIterator will be invoked, and whatever object that's on Symbol.asyncIterator
will be returned, if it exists, without regard to whether it's actually async or not.
With the iterator, when iterated over with for await
, each value returned by the iterator will be await
ed:
b. If iteratorKind is async, then set nextResult to ?
Await(nextResult)
.
And it's perfectly fine to await
something that isn't a Promise, it's just odd:
(async () => {
const item = await 'foo';
console.log(item);
})();
await
will unwrap a Promise if the expression to its right is a Promise, and will leave it unchanged otherwise.
Upvotes: 2