[英]Making an asynchronous generator *[Symbol.asyncIterator] without async/await but with promises only
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?假设我不想使用
async / await
抽象,那么我如何仅通过 Promise 实现相同的功能?
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
;但它返回
undefined
; presumingly yield
not being a function.假设
yield
不是 function。 I checked out this question but it's not about generators and no yield
is involved.我检查了这个问题,但它与生成器无关,也不涉及
yield
。 Is there a way to implement this?有没有办法实现这个?
Edit: yield await promise
in an async generator seems to be wasteful.编辑:异步生成器中的
yield await promise
似乎很浪费。 Use yield promise
instead.请改用
yield promise
。 Check the comments under TJ Crowders answer.检查 TJ Crowders 答案下的评论。
An async iterator has to produce promises for result objects (objects in the form {value, done}
).异步迭代器必须为结果对象(形式为
{value, done}
的对象)生成 Promise。 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.您不能通过使用 promise 作为
yield
的操作数在非async
生成器中执行此操作,因为您提供的操作数将成为结果yield
中的value
,而不是结果 ZA8CFDE6331BD59EB2AC96F8911C4B666 本身。 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}>
). ...在
async
生成器 function 中,它为{value: 42, done: false}
生成一个 promise (使用 TypeScript 表示法, 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}
). ...在非
async
生成器 function 中,它产生{value: somePromise, done: false}
(TS: {value: Promise, done: false}
)。 That's not what an asyncIterator
function is defined to return.这不是
asyncIterator
function 定义返回的内容。 It has to return a promise for the {value, done}
object, not a non-promise object.它必须为
{value, done}
object 返回一个 promise,而不是无承诺的 object。
So you have at least two choices if you want to avoid using async
/ await
:因此,如果您想避免使用
async
/ await
,您至少有两种选择:
Define your object such that it isn't async iterable, just iterable, and the values it produces are {value: Promise, done: boolean}
.定义您的 object 使其不是异步可迭代的,只是可迭代的,并且它产生的值是
{value: Promise, done: boolean}
。
Define it as async iterable and don't use yield
.将其定义为异步可迭代并且不要使用
yield
。 Write the next
method explicitly.显式编写
next
方法。
I'd definitely go for #2 for the semantics.对于语义,我肯定会为#2 使用 go。 It's hard to show precisely without more information about your object, but roughly:
如果没有关于 object 的更多信息,很难准确显示,但大致如下:
[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:或者,如果您希望异步迭代器 object 具有标准原型,请将其放在可以重用的地方:
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};
});
}
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.