EventMachine と連携するには、リクエスト ロジックを非同期にする必要があります。 em-http-requestを使用することをお勧めします。ここで使用方法の例を見つけることができます。リクエストを並行して実行する方法を示しています。複数の接続を並行して実行するためのさらに優れたインターフェースは、同じ gemのMultiRequest クラスです。
リクエストをキューに入れ、一定数のリクエストのみを並行して実行したい場合は、次のようにすることができます:
EM.run do
urls = [...] # regular array with URLs
active_requests = 0
# this routine will be used as callback and will
# be run when each request finishes
when_done = proc do
active_requests -= 1
if urls.empty? && active_requests == 0
# if there are no more urls, and there are no active
# requests it means we're done, so shut down the reactor
EM.stop
elsif !urls.empty?
# if there are more urls launch a new request
launch_next.call
end
end
# this routine launches a request
launch_next = proc do
# get the next url to fetch
url = urls.pop
# launch the request, and register the callback
request = EM::HttpRequest.new(url).get
request.callback(&when_done)
request.errback(&when_done)
# increment the number of active requests, this
# is important since it will tell us when all requests
# are done
active_requests += 1
end
# launch three requests in parallel, each will launch
# a new requests when done, so there will always be
# three requests active at any one time, unless there
# are no more urls to fetch
3.times do
launch_next.call
end
end
emptor に注意してください。上記のコードで見逃した詳細がある可能性が非常に高いです。
私の例のロジックに従うのが難しいと思われる場合は、イベント プログラミングの世界へようこそ。読み取り可能なイベント コードを記述するのは非常に困難です。それはすべて後退します。最後から読み始めると役立つ場合もあります。
ダウンロードを開始した後にリクエストを追加したくないと思いましたが、質問のコードからはそう見えませんが、必要に応じてコードを書き直して、のEM::Queue
代わりにを使用できます通常の配列であり、EM.stop
停止しないため、 を行う部分を削除します。アクティブなリクエストの数を追跡するコードもおそらく削除できます。これは関係ないためです。重要な部分は次のようになります。
launch_next = proc do
urls.pop do |url|
request = EM::HttpRequest.new(url).get
request.callback(&launch_next)
request.errback(&launch_next)
end
end
また、私のコードは実際には応答に対して何もしないことに注意してください。when_done
応答はルーチンに引数として渡されます(最初の例)。成功とエラーに対しても同じことを行いますが、実際のアプリケーションではやりたくないかもしれません。