Ruby EventMachine – как вернуть значения из EM::Deferrable в основной цикл EM?

Я играю с EventMachine уже несколько дней, у которого ИМХО крутая кривая обучения ;-) Я пытаюсь вернуть хэш, вызывая HttpHeaderCrawler.query(), который мне нужен в обратном вызове. Но в этом случае я получаю не хэш {'http_status' => xxx, 'http_version' => xxx}, а сам объект EventMachine::HttpClient.

Я хочу сохранить блок EM.run в чистоте и хочу выполнять всю логику в собственных классах/модулях, так как же вернуть такое значение в основной цикл, чтобы получить к нему доступ с помощью обратного вызова? Спасибо заранее ;-)

#!/usr/bin/env ruby

require 'eventmachine'
require 'em-http-request'

class HttpHeaderCrawler
  include EM::Deferrable

  def query(uri)
    http = EM::HttpRequest.new(uri).get
    http.callback do
      http_header = {
        "http_status" => http.response_header.http_status,
        "http_version" => http.response_header.http_version
      }
      puts "Returns to EM main loop: #{http_header}"
      succeed(http_header)
    end
  end
end

EM.run do
  domains = ['http://www.google.com', 'http://www.facebook.com', 'http://www.twitter.com']
  domains.each do |domain|
    hdr = HttpHeaderCrawler.new.query(domain)
    hdr.callback do |header|
      puts "Received from HttpHeaderCrawler: #{header}"
    end
  end
end

Этот фрагмент выдает следующий результат:

Returns to EM main loop: {"http_status"=>302, "http_version"=>"1.1"}
Received from HttpHeaderCrawler: #<EventMachine::HttpClient:0x00000100d57388>
Returns to EM main loop: {"http_status"=>301, "http_version"=>"1.1"}
Received from HttpHeaderCrawler: #<EventMachine::HttpClient:0x00000100d551a0>
Returns to EM main loop: {"http_status"=>200, "http_version"=>"1.1"}
Received from HttpHeaderCrawler: #<EventMachine::HttpClient:0x00000100d56280>

person ctp    schedule 26.10.2011    source источник
comment
Мне нравится это руководство Мартина Лограна, в котором предлагаются способы обхода спагетти-кода обратного вызова.   -  person sarnold    schedule 27.10.2011
comment
Да, я знаю этот учебник. Хороший подход для начала с EM. Но чего я не понимаю: Мартин возвращает значение в своем образце em-http-request так же, как я делаю в приведенном выше фрагменте. Не вижу, что происходит в моем случае   -  person ctp    schedule 27.10.2011
comment
Это странно. Замена query(uri) на initialize(uri) в HttpHeaderCrawler и hdr = HttpHeaderCrawler.new.query(domain) на hdr = HttpHeaderCrawler.new(domain) решает все. Но почему?   -  person ctp    schedule 27.10.2011
comment
Единственное отличие, которое я заметил, заключается в том, что в его коде используются self.succeed() и self.fail(), а в вашем коде self. отсутствует. Этого достаточно, чтобы создать проблему?   -  person sarnold    schedule 27.10.2011


Ответы (1)


Я думаю, проблема в том, что #query возвращает http.callback, который возвращает сам объект http, тогда как он должен возвращать self, то есть HttpHeaderCrawler. Посмотрите, работает ли это.

def query(uri)
  http = EM::HttpRequest.new(uri).get
  http.callback do
    http_header = {
      "http_status" => http.response_header.http_status,
      "http_version" => http.response_header.http_version
    }
    puts "Returns to EM main loop: #{http_header}"
    succeed(http_header)
  end
  self
end
person Eric G    schedule 27.10.2011
comment
Эй, Эрик. Круто, это как раз и есть причина моей беды. Теперь все работает отлично СПАСИБО :) - person ctp; 27.10.2011