2016-11-06 16 views
2

在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庫,或更適合這種情況的其他庫?

回答

5

經過對併發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