在Ruby on Rails中,如何在发送响应之前等待多个异步操作完成?

mbzjlibv  于 2023-02-03  发布在  Ruby
关注(0)|答案(1)|浏览(92)

在我做的一些web开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖于另一个的结果。我希望事情能够在后台运行。我发现concurrent-ruby library似乎工作得很好。通过将它混合到你创建的类中,这个类的方法有异步版本,在后台线程上运行,这导致我编写了如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法,该方法发送HTTP请求:

def index
  op1_result = FirstAsyncWorker.new.async.work
  op2_result = SecondAsyncWorker.new.async.work
  
  render text: results(op1_result, op2_result)
end

然而,控制器会在action方法执行结束时隐式地呈现一个响应,因此响应会在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

我不使用互斥锁是因为两个线程不访问相同的内存。但是我想知道这是否是最好的方法。有没有更好的方法来使用concurrent-ruby库,或者其他更适合这种情况的库?

jc3wubiy

jc3wubiy1#

在对concurrent-ruby库做了更多的研究之后,我最终回答了自己的问题。Future s最终就是我所追求的!简单地说,它们在后台线程中执行一个代码块,并试图访问Future的计算值,这会阻塞主线程,直到后台线程完成其工作。

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

包含render的行阻塞,直到两个异步任务都完成,此时result可以开始运行。

相关问题