在Ruby on Rails中发送响应之前,如何等待多个异步操作完成?
问题描述:
在Ruby on Rails中,我意识到它本质上是同步的,开发人员可以异步执行同步事件。在我开发的一些web dev中,我有多个操作开始,比如对外部API的GET请求,我希望它们都在同一时间启动,因为它们不依赖于另一个的结果。我发现concurrent-ruby library似乎运作良好。通过将它混合到您创建的类中,类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编码的类,其中混合了Concurrent :: Async模块,并编写了一个名为“work”的方法,用于发送HTTP请求:在Ruby on Rails中发送响应之前,如何等待多个异步操作完成?
def index
op1_result = FirstAsyncWorker.new.async.work
op2_result = SecondAsyncWorker.new.async.work
render text: results(op1_result, op2_result)
end
但是,控制器将隐含地在操作方法执行结束时呈现响应。因此,在op1_result和op2_result获得值之前发送响应,唯一发送到浏览器的是“#”。
我到目前为止的解决方案是使用Ruby线程。我写如下代码:
def index
op1_result = nil
op2_result = nil
op1 = Thread.new do
op1_result = get_request_without_concurrent
end
op2 = Thread.new do
op2_result = get_request_without_concurrent
end
# Wait for the two operations to finish
op1.join
op2.join
render text: results(op1_result, op2_result)
end
我不使用互斥锁,因为两个线程不访问相同的内存。但我想知道这是否是最好的方法。有没有更好的方式来使用并发ruby库,或更适合这种情况的其他库?
答
经过对并发ruby库的更多研究,我最终回答了自己的问题。 “未来”最终成为我之后的事情!简而言之,他们在后台线程中执行一段代码,并尝试访问Future的计算值,阻止主线程,直到该后台线程完成其工作。我的Rails控制器动作结束看起来像:
def index
op1 = Concurrent::Future.execute { get_request }
op2 = Concurrent::Future.execute { another_request }
render text: "The result is #{result(op1.value, op2.value)}."
end
与“渲染”的块,直到两个异步任务已经完成,此时“结果”可以开始运行线。
如果有人正在做这样的编程,找到这个,并希望看到一个Rails应用程序实现这些异步技术的例子,我已经主持了public example。