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

Ruby 3中如何收集多个调度Fiber的结果?求更简洁实现方式

如何用Ruby Fiber调度器实现类似JavaScript Promise.all的并发任务收集?

你的朴素实现可以正常工作,但借助Async库的原生API能大幅简化代码,无需手动轮询结果数组。Async框架提供了Async.gather方法,完全对应JavaScript中Promise.all的功能——并发执行多个任务,等待全部完成后按任务定义顺序返回结果集合。

优化后的实现如下:

require 'async'

def io_work(t)
  sleep t
  :ok
end

Async do
  # 构建并发任务列表
  tasks = [0.1, 0.3, 'cow'].each_with_index.map do |t, i|
    task_id = i + 1
    Async.task do
      puts "Starting fiber #{task_id}"
      begin
        result = io_work(t)
        puts "Done working for #{t} seconds in fiber #{task_id}"
        [task_id, result]
      rescue => e
        puts "Execution failed in fiber #{task_id}: #{e.message}"
        [task_id, :error]
      end
    end
  end

  # 等待所有任务完成并收集结果,效果等同于Promise.all
  results = Async.gather(*tasks)
  puts "Results: #{results}"
end

关键说明:

  • Async.gather:自动管理所有任务的生命周期,等待全部任务完成后返回结果数组,结果顺序与任务定义顺序一致(区别于你原实现中按任务完成顺序插入的逻辑,更贴合Promise.all的行为)
  • Async.task:替代直接调用Fiber.schedule,是Async框架推荐的任务创建方式,能被gather正确追踪和管理
  • 异常隔离:每个任务内部处理异常,单个任务失败不会中断其他任务执行,失败结果会被正常收集

如果需要保持原实现中按任务完成顺序收集结果的逻辑,可以使用Async::Barrier:

require 'async'

def io_work(t)
  sleep t
  :ok
end

Async do
  results = []
  barrier = Async::Barrier.new

  [0.1, 0.3, 'cow'].each_with_index do |t, i|
    task_id = i + 1
    barrier.async do
      puts "Starting fiber #{task_id}"
      begin
        result = io_work(t)
        puts "Done working for #{t} seconds in fiber #{task_id}"
        results << [task_id, result]
      rescue => e
        puts "Execution failed in fiber #{task_id}: #{e.message}"
        results << [task_id, :error]
      end
    end
  end

  # 等待屏障内所有任务完成
  barrier.wait
  puts "Results: #{results}"
end

内容的提问来源于stack exchange,提问作者Erik Madsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:50:24