You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似Promise.any的多异步Generator并发取值?

实现多异步生成器的并发输出

你需要的是一个能并发监听多个异步生成器、只要有生成器产出值就立即向外输出、直到所有生成器耗尽的工具函数,类似你设想的Generator.any但不会中途终止其他生成器。

核心实现思路

通过Promise.race跟踪所有活跃生成器的下一次产出请求,每次拿到最先完成的结果后,将该生成器的下一次产出请求重新加入监听队列,循环直到所有生成器都处理完毕。

具体代码实现

// 实现需求的合并异步生成器工具函数
async function* mergeAsyncGenerators(generators) {
  // 初始化所有生成器的首次next请求Promise
  const pendingPromises = generators.map(async gen => {
    const result = await gen.next();
    return { gen, result };
  });

  while (pendingPromises.length > 0) {
    // 等待第一个完成的产出请求
    const { gen, result } = await Promise.race(pendingPromises);
    
    // 移除当前已完成的Promise
    const targetIndex = pendingPromises.findIndex(p => 
      p === (async () => ({ gen, result }))()
    );
    pendingPromises.splice(targetIndex, 1);

    // 如果生成器未耗尽,添加下一次next请求
    if (!result.done) {
      pendingPromises.push(async () => {
        const nextResult = await gen.next();
        return { gen, result: nextResult };
      }());
    }

    // 立即产出当前获取到的值
    yield result.value;
  }
}

// 模拟你的values异步生成器(带随机延迟体现并发效果)
async function* values(input) {
  await new Promise(resolve => setTimeout(resolve, Math.random() * 1000));
  yield `输入${input}的第一个值`;
  await new Promise(resolve => setTimeout(resolve, Math.random() * 1000));
  yield `输入${input}的第二个值`;
}

// 你的包装生成器函数
async function* generateValues() {
  const inputs = [1,2,3,4,5];
  const generators = inputs.map(input => values(input));
  
  // 使用合并函数实现并发输出
  for await (const value of mergeAsyncGenerators(generators)) {
    yield value;
  }
}

// 测试调用
(async () => {
  for await (const val of generateValues()) {
    console.log(val);
  }
})();

代码说明

  1. mergeAsyncGenerators函数:

    • 启动阶段为每个生成器创建首次next()请求的Promise
    • 循环通过Promise.race抢占式获取最先完成的产出结果
    • 未耗尽的生成器会被持续加入下一轮监听,保证所有结果都能被收集
    • 拿到结果后立即向外产出,完全符合“有值就输出”的需求
  2. 测试效果:
    由于values函数加入了随机延迟,运行时会看到不同输入的结果交替输出,而非按输入顺序串行输出所有内容。

内容的提问来源于stack exchange,提问作者Mahesh Bansod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 21:57:10