【问题标题】:How to map over async generators?如何映射异步生成器?
【发布时间】:2021-08-20 00:04:43
【问题描述】:

假设我们有一个异步生成器:

exports.asyncGen = async function* (items) {
  for (const item of items) {
    const result = await someAsyncFunc(item)
    yield result;
  }
}

是否可以映射这个生成器?基本上我想这样做:

const { asyncGen } = require('./asyncGen.js')

exports.process = async function (items) {
  return asyncGen(items).map(item => {
    //... do something
  })
}

截至目前,.map 无法识别异步迭代器。

替代方法是使用 for await ... of ,但这远不如 .map 优雅

【问题讨论】:

  • .map() 仅存在于数组上,而不存在于生成器上——异步与否。

标签: javascript node.js iterator map-function async-iterator


【解决方案1】:

提供this method 的iterator methods proposal 仍仅处于第2 阶段。你可以使用somepolyfill,或者编写你自己的map帮助函数:

async function* map(asyncIterable, callback) {
    let i = 0;
    for await (const val of asyncIterable)
        yield callback(val, i++);
}

exports.process = function(items) {
    return map(asyncGen(items), item => {
       //... do something
    });
};

【讨论】:

    【解决方案2】:

    替代方法是使用for await ... of,但这远不如.map 优雅

    对于一个优雅高效的解决方案,这里有一个使用iter-ops 库的解决方案:

    import {pipe, map} from 'iter-ops';
    
    const i = pipe(
        asyncGen(), // your async generator result
        map(value => /*map logic*/)
    ); //=> AsyncIterable
    
    • 它很优雅,因为语法干净、简单,并且适用于任何可迭代或迭代器,而不仅仅是异步生成器。
    • 它更加灵活且可重复使用,因为您可以将许多其他运算符添加到同一管道中。

    由于它生成标准 JavaScript AsyncIterable,您可以这样做:

    for await(const a of i) {
        console.log(a); //=> print values
    }
    

    附:我是iter-ops的作者。

    【讨论】:

      猜你喜欢
      • 2018-12-05
      • 1970-01-01
      • 2016-07-05
      • 2018-03-27
      • 2015-12-13
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 2016-12-02
      相关资源
      最近更新 更多