簡體   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