繁体   English   中英

制作一个没有 async/await 但只有 Promise 的异步生成器 *[Symbol.asyncIterator]

[英]Making an asynchronous generator *[Symbol.asyncIterator] without async/await but with promises only

现在这段代码工作得很好

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;
  };
};

假设我不想使用async / await抽象,那么我如何仅通过 Promise 实现相同的功能?

我天真地尝试过

*[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);
  };
};

但它返回undefined 假设yield不是 function。 我检查了这个问题,但它与生成器无关,也不涉及yield 有没有办法实现这个?

编辑:异步生成器中的yield await promise似乎很浪费。 请改用yield promise 检查 TJ Crowders 答案下的评论。

异步迭代器必须为结果对象(形式为{value, done}的对象)生成 Promise。 您不能通过使用 promise 作为yield的操作数在非async生成器中执行此操作,因为您提供的操作数将成为结果yield中的value ,而不是结果 ZA8CFDE6331BD59EB2AC96F8911C4B666 本身。 也就是说,当你这样做时:

yield 42;

...在async生成器 function 中,它为{value: 42, done: false}生成一个 promise (使用 TypeScript 表示法, Promise<{value: 42, done: false}> 如果你这样做:

yield somePromise;

...在async生成器 function 中,它产生{value: somePromise, done: false} (TS: {value: Promise, done: false} )。 这不是asyncIterator function 定义返回的内容。 它必须为{value, done} object 返回一个 promise,而不是无承诺的 object。

因此,如果您想避免使用async / await ,您至少有两种选择:

  1. 定义您的 object 使其不是异步可迭代的,只是可迭代的,并且它产生的值是{value: Promise, done: boolean}

  2. 将其定义为异步可迭代并且不要使用yield 显式编写next方法。

对于语义,我肯定会为#2 使用 go。 如果没有关于 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};
            });
        }
    };
}

或者,如果您希望异步迭代器 object 具有标准原型,请将其放在可以重用的地方:

const asyncIteratorPrototype =
    Object.getPrototypeOf(
        Object.getPrototypeOf(
            (async function *(){}).prototype
        )
    );

然后:

[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM