微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决制作一个异步生成器 *[Symbol.asyncIterator] 没有 async/await 但只有承诺

在这代码工作正常

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 不是函数。我查看了 this 问题,但它与生成器无关,也不涉及 yield。有没有办法实现这个?

编辑: yield await promise 在异步生成器中似乎很浪费。请改用 yield promise。查看 T.J. 下的评论群众回答。

解决方法

异步迭代器必须为结果对象({value,done} 形式的对象)生成承诺。你不能在非async生成器中使用promise作为yield的操作数,因为你给yield的操作数变成了value 在结果对象中,而不是结果对象本身。也就是说,当你这样做时:

yield 42;

...在一个 async 生成器函数中,它为 {value: 42,done: false} 生成一个 promise(使用 TypeScript 符号 Promise<{value: 42,done: false}>)。如果你这样做:

yield somePromise;

...在 non-async 生成器函数中,它生成 {value: somePromise,done: false} (TS: {value: Promise,done: false})。这不是定义 asyncIterator 函数返回的内容。它必须返回 {value,done} 对象的承诺,而不是非承诺对象。

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

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

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

我肯定会为语义选择#2。如果没有关于您的对象的更多信息,很难准确显示,但大致如下:

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。