Ваша логика запроса должна быть асинхронной, чтобы она работала с EventMachine, я предлагаю вам использовать em-http-request . Вы можете найти пример того, как его использовать, здесь , он показывает, как выполнять запросы параллельно. Еще лучшим интерфейсом для параллельного запуска нескольких соединений является класс 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
Будьте бдительны, возможно, есть некоторые детали, которые я пропустил в коде выше.
Если вы считаете, что в моем примере трудно следовать логике, добро пожаловать в мир четного программирования. Это действительно сложно написать читаемый код. Все идет в обратном направлении. Иногда это помогает начать чтение с конца.
Я предположил, что вы не хотите добавлять больше запросов после начала загрузки, это не похоже на код из вашего вопроса, но если вы хотите, вы можете переписать мой код, чтобы использовать 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
(в первом примере). Я также делаю то же самое для успеха и ошибок, чего вы, возможно, не захотите делать в реальном приложении.