Now this code works just fine
async *[Symbol.asyncIterator](){
var promise;
while (true){
promise = this.#HEAD.promise;
this.size--;
this.#HEAD.next ? this.#HEAD = this.#HEAD.next
: this.#LAST = void 0;
yield await promise;
};
};
Say if i don't want to use the async / await
abstraction then how can i implement the same functionality only with promises?
I naively tried
*[Symbol.asyncIterator](){
var promise;
while (true){
promise = this.#HEAD.promise;
this.size--;
this.#HEAD.next ? this.#HEAD = this.#HEAD.next
: this.#LAST = void 0;
promise.then(yield);
};
};
but it returns undefined
; presumingly yield
not being a function. I checked out this question but it's not about generators and no yield
is involved. Is there a way to implement this?
Edit: yield await promise
in an async generator seems to be wasteful. Use yield promise
instead. Check the comments under TJ Crowders answer.
An async iterator has to produce promises for result objects (objects in the form {value, done}
). You can't do that in a non- async
generator by using a promise as yield
's operand because the operand you give yield
becomes the value
in the result object, not the result object itself. That is, when you do:
yield 42;
...in an async
generator function, it produces a promise for {value: 42, done: false}
(using TypeScript notation, Promise<{value: 42, done: false}>
). If you do:
yield somePromise;
...in a non - async
generator function, it produces {value: somePromise, done: false}
(TS: {value: Promise, done: false}
). That's not what an asyncIterator
function is defined to return. It has to return a promise for the {value, done}
object, not a non-promise object.
So you have at least two choices if you want to avoid using async
/ await
:
Define your object such that it isn't async iterable, just iterable, and the values it produces are {value: Promise, done: boolean}
.
Define it as async iterable and don't use yield
. Write the next
method explicitly.
I'd definitely go for #2 for the semantics. It's hard to show precisely without more information about your object, but roughly:
[Symbol.asyncIterator](){
let current = this.#HEAD;
return {
next() {
if (/*done condition*/) {
return Promise.resolve({done: true});
}
return current.promise.then(value => {
current = current.next; // or whatever
return {value, done: false};
});
}
};
}
Or if you want the async iterator object to have the standard prototype, put this somewhere where you can reuse it:
const asyncIteratorPrototype =
Object.getPrototypeOf(
Object.getPrototypeOf(
(async function *(){}).prototype
)
);
then:
[Symbol.asyncIterator](){
let current = this.#HEAD;
return Object.assign(Object.create(asyncIterator), {
next() {
if (/*done condition*/) {
return Promise.resolve({done: true});
}
return current.promise.then(value => {
current = current.next; // or whatever
return {value, done: false};
});
}
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.