JavaScript 异步迭代器的连接/归约

7

我有一个类似这样的异步迭代器:

async function* getLines() {
  for (let index = 0; index < 10; index++) {
    const response = await fetch('/resource/' + index);
    const data = await response.text();
    yield data;
  }
}

我能够使用 for await 来消费它:

let source = '';
for await (const line of getLines()) {
  console.log('line');
  source += line + '\n';
}

return source;

但我想知道是否有一种方法可以使用类似于Array.from[...]的东西来实现从异步迭代器中连接项目以形成字符串的相同效果。

Array.from(await getLines())[...getLines()]本身并没有意义,因为生成器本身不会被单个项目等待,就像在 for await 结构中一样。是否有像Array.fromAwait(getLines())这样的东西,还是我必须自己编写像在使用for await示例中那样的代码?

3个回答

4

当前规范不支持在异步迭代器上使用像 .reduce 这样的操作符,除非您使用的是Node(在这种情况下,您可以使用 AsyncIterator -> Readable.from -> 异步迭代器)。否则,您将需要使用一个类似于axax的用户自定义库。

现在有一个tc39提案来添加迭代器助手。使用这些助手,您将能够执行以下操作:

const source = await getLines().reduce((l, cur) => l + cur);

当前处于第二阶段,您可以使用填充程序。


你能详细介绍一下 Readable.from 吗?我不太确定该如何使用它。 - Tomáš Hübelbauer
1
Readable.from 将异步迭代器转换为 Node.js 流,您可以对其进行转换并利用流本身是异步可迭代的事实来获取异步迭代器。请参见 https://nodejs.org/api/stream.html#stream_stream_readable_from_iterable_options - Benjamin Gruenbaum
1
@BenjaminGruenbaum 但是可读流也没有reduce方法?我可能在这里漏掉了什么。 - Bergi

0

如今,借助可迭代对象和支持它们的各种库,编程变得更加简单。

下面的示例基于一个名为iter-ops的库:

import {pipeAsync, map, reduce, wait} from 'iter-ops';

const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; // your resource id-s

const i = pipeAsync(
    indexes,
    map(a => fetch('/resource/' + a).then(r => r.text())),
    wait(), // resolve each request
    reduce((r, c) => r + '\n' + c)
); //=> AsyncIterable<string>

// test:
(async function () {
    const source = await i.first; // iterate, and wait for the first value
    console.log(source); // all the lines joint together
})();

这也是将源ID列表转换为最终数据的最快方法。

P.S. 我是作者。


0
你可以使用 IX (交互式扩展),它是由 RxJs 社区创建的库,具有与 RxJs 相同的操作符,但可与同步和异步迭代器一起使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接