-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why does AsyncFromSyncIterator exist? #1765
Comments
When you say “not broad agreement”, can you provide some more detailed comparisons? |
Sure, here's a gist. Roughly speaking, JSC and V8 have 1 additional queue item per step, SpiderMonkey has 2, and XS has 0 (i.e., it behaves as if it does no wrapping at all). |
QJS also has one tick, and the iterator proposal is planning to use AsyncFromSyncIteratorPrototype so that you don't have to worry about whether or not you've wrapped a sync iterator when you do |
It has the additional feature of unwrapping yielded promises from synchronous iterators: function *foo() {
for (let i = 1; i <= 3; i++) {
yield Promise.resolve(i);
}
}
// This logs: Promise { 1 }, Promise { 2 }, Promise { 3 }
function forOfFoo() {
for (let value of foo()) {
console.log(value);
}
}
forOfFoo();
// This logs: 1, 2, 3
async function forAwaitOfFoo() {
for await (let value of foo()) {
console.log(value);
}
}
forAwaitOfFoo(); |
To demonstrate what @ExE-Boss is saying, consider function* g(){
yield 0; yield Promise.resolve(1);
}
(async function() {
for await (let value of g()) {
console.log(value);
}
})(); This prints But if instead we bypassed AsyncFromSyncIIterator by doing (async function() {
for await (let value of { [Symbol.asyncIterator]: g }) {
console.log(value);
}
})(); we would get Presumably that's why this exists. I'll go ahead and close this. |
AsyncFromSyncIterator
is a spec fiction converts sync iterators into async iterators, i.e., iterators which return promises. It is not accessible to ECMAScript code (as of #1474).It is used in two places: in for-await-of loops and in
yield*
in async generators. Specifically, it is used when those constructs are given objects which haveSymbol.iterator
but notSymbol.asyncIterator
.But both of those places always
Await
the result of theNextMethod
of the iterator they're working with, and that macro wraps its argument in aPromise
anyway. Indeed, if you make an object which has a sync iterator in itsSymbol.asyncIterator
property, that will work fine:As far as I can tell, the only only observable difference made by wrapping is that it causes there to be additional PromiseJob queue items (although it seems there is not broad agreement among the engines about exactly how many).
So what's the point of wrapping the sync iterator? Is it just to cause these additional queue items?
The text was updated successfully, but these errors were encountered: