【问题标题】:How can I convert an async iterator to an array?如何将异步迭代器转换为数组?
【发布时间】:2019-11-02 04:57:15
【问题描述】:

鉴于我有一个异步生成器:

async function* generateItems() {
    // ...
}

将所有结果迭代到数组中的最简单方法是什么?我尝试了以下方法:

// This does not work
const allItems = Array.from(generateItems());
// This works but is verbose
const allItems = [];
for await (const item of generateItems()) {
    allItems.push(item);
}

(我知道这在生产应用程序中可能是不好的做法,但它对于原型设计很方便。)

【问题讨论】:

  • 这行得通,但很冗长 不要认为你能得到比这更好的,因为每个项目都需要单独 awaited 才能访问下一个承诺
  • allItems = await generateItems().toArray()currently proposed
  • 有一个新的Array.asyncFrom 提案提到了这篇文章。

标签: javascript async-await


【解决方案1】:

这是一个简单的函数,可以将异步迭代器转换为数组,而不必包含整个包。

async function toArray(asyncIterator){ 
    const arr=[]; 
    for await(const i of asyncIterator) arr.push(i); 
    return arr;
}

【讨论】:

  • 好一个,与接受的答案see on GitHub中实现的相同
  • 谢谢你,惊讶地发现它不是一阶概念......
【解决方案2】:

您的解决方案是我所知道的唯一一个。这是一个 TypeScript 函数:

async function gen2array<T>(gen: AsyncIterable<T>): Promise<T[]> {
    const out: T[] = []
    for await(const x of gen) {
        out.push(x)
    }
    return out
}

TypeScript Playground

【讨论】:

  • 您知道为什么必须专门为AsyncGenerator&lt;T&gt; 进行类型提示吗?我想要一个接受AsyncIterator&lt;T&gt; 的更通用的函数,它是AsyncGenerator&lt;T&gt; 的基本类型——但由于某种原因它不起作用。
  • @mindplay.dk 我认为它适用于AsyncIterable,但不适用于AsyncIterator。我添加了一个 TS Playground 链接——这符合你的要求吗?
  • 啊哈!是的,这行得通 - 谢谢 :-)
【解决方案3】:

看起来async-iterator-to-array npm 库是这样做的:

安装

npm install --save async-iterator-to-array

用法

const toArray = require('async-iterator-to-array')

async function * iterator (values) {
  for (let i = 0; i < values.length; i++) {
    yield values[i]
  }
}

const arr = await toArray(iterator([0, 1, 2, 3, 4]))

console.info(arr) // 0, 1, 2, 3, 4

【讨论】:

  • 请注意,引用的包在内部的执行方式与 OP 标记为“详细”的方式完全相同。想想看,你的项目中真的需要另一个依赖吗?...
  • @1valdis 请注意,此答案由 OP 编写。
猜你喜欢
  • 1970-01-01
  • 2021-08-26
  • 2019-06-20
  • 2023-01-30
  • 2018-06-05
  • 2021-05-26
相关资源
最近更新 更多