您的请求逻辑必须是异步的才能与 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
警告购买者,我很可能在上面的代码中遗漏了一些细节。
如果您认为很难遵循我的示例中的逻辑,欢迎来到事件编程的世界。编写可读的事件代码真的很棘手。这一切都倒退了。有时从头开始阅读会有所帮助。
我假设您在开始下载后不想添加更多请求,从您问题中的代码来看,它看起来不像,但如果您愿意,您可以重写我的代码以使用 anEM::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
例程(在第一个示例中)。我也对成功和错误做同样的事情,你可能不想在实际应用程序中这样做。