简体   繁体   English

创建异步迭代器的最佳实践是什么? 我应该使用异步生成器 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?

This code works as expected:此代码按预期工作:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getAsyncData() {
    await sleep(1000);  // simulate database/network delay...
    return [1, 2, 3, 4, 5];  // ...then return some data
}

const asyncIterable = (async function* filterAsyncData() {
    const items = await getAsyncData();

    for (const item of items) {
        yield item;
    }
})();

const asyncIterable2 = {
    [Symbol.asyncIterator]() {
        return {
            values: null,
            idx: 0,
            async next() {
                if (this.values === null) {
                    this.values = await getAsyncData();
                }

                if (this.idx < this.values.length) {
                    this.idx = this.idx + 1;
                    return Promise.resolve({ value: this.values[this.idx - 1], done: false });
                }

                return Promise.resolve({ done: true });
            }
        };
    }
};

async function main() {
    for await (const filteredItem of asyncIterable) {
        console.log(filteredItem);
    }
}

main()

It does not mather if I use asyncIterable or asyncIterable2 in the main function, I always get the same result.如果我在main function 中使用asyncIterableasyncIterable2则不会,我总是得到相同的结果。 What is the best practice to define my iterable?定义我的可迭代对象的最佳实践是什么? Are there any guidelines about which option is preferred?是否有关于首选哪个选项的指导方针? Why?为什么?

It's the same as for synchronous iterators : generator functions are much easier to write, and easier to get correct, than implementing the iterator object manually.与同步迭代器相同:生成器函数比手动实现迭代器 object 更容易编写,也更容易正确。 Do this only if you need some non-standard behaviour that cannot be achieved otherwise.仅当您需要一些其他方式无法实现的非标准行为时才执行此操作。 With asynchronous generator functions specifically, you even get the proper queueing of next calls for free, which is a real headache to get right (your asyncIterable2 fails this 1 ).特别是使用异步生成器功能,您甚至可以免费获得next调用的正确排队,这真是令人头疼(您的asyncIterable2失败了 this 1 )。

The most common implementation of iterables is to make the Symbol.asyncIterator method an async generator method:最常见的可迭代实现是使Symbol.asyncIterator方法成为异步生成器方法:

const asyncIterable = {
    async *[Symbol.asyncIterator]() {
         yield* await getAsyncData();
    },
};

1: const it = asyncIterable2[Symbol.asyncIterator](); it.next(); it.next() 1: const it = asyncIterable2[Symbol.asyncIterator](); it.next(); it.next() const it = asyncIterable2[Symbol.asyncIterator](); it.next(); it.next() const it = asyncIterable2[Symbol.asyncIterator](); it.next(); it.next() - without any await s in between - will call getAsyncData twice, because this.values == null in both calls const it = asyncIterable2[Symbol.asyncIterator](); it.next(); it.next() - 中间没有任何await - 将调用getAsyncData两次,因为this.values == null在两个调用中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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