简体   繁体   English

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

[英]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 ,您至少有两种选择:

  1. 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}

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

相关问题 For..of 和 Symbol.asyncIterator - For..of with Symbol.asyncIterator 使用javascript的Symbol.asyncIterator与等待循环 - Using javascript's Symbol.asyncIterator with for await of loop 创建异步迭代器的最佳实践是什么? 我应该使用异步生成器 function 还是使用 Symbol.asyncIterator? - What is the best practice to create an async iterator? Should I use an async generator function or rather use Symbol.asyncIterator? 数组中的内置 Symbol.asyncIterator - Built-in Symbol.asyncIterator in Array Promises - 如何在没有 async / await 的情况下使异步代码同步执行? - Promises - How to make asynchronous code execute synchronous without async / await? 在 asyncIterator 生成器 function 中等待异步操作 - Wait for an async operation inside asyncIterator generator function async-await 是否仅与 Promise 一起使用? - Is async-await only used with promises? 将异步和同步工作与异步/等待和/或 javascript 中的承诺混合在一起 - Mixing asynchronous and synchronous work with async/await and/or promises in javascript 承诺和异步/等待组合,等待异步操作的理想方法? - Promises and async/await combination, ideal way to wait for asynchronous operations? 强制异步功能同步,无需等待异步 - Force asynchronous function to be synchronous without async await
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM