EM::DefaultDeferrable の使い道
というわけで
http://d.hatena.ne.jp/eagletmt/20110211/1297413439
は
class HtmlDocument include EM::Deferrable ...
で良いのであった…
では EM::DefaultDeferrable は何のために提供されているのかというと
DefaultDeferrable is an otherwise empty class that includes Deferrable. This is very useful when you just need to return a Deferrable object as a way of communicating deferred status to some other part of a program.
http://eventmachine.rubyforge.org/EventMachine/DefaultDeferrable.html
とあるので,単に完了/失敗を伝えたいときに使うとよさそう.
em-http-request のようにクライアント用途で EventMachine を使うと,いつ EM.stop するかがめんどくさかったりするので,例えばこういう使い方があるのかもしれない.
#!/usr/bin/ruby # coding: utf-8 require 'em-http' require 'nokogiri' class HtmlDocument include EM::Deferrable attr_reader :http, :parser def initialize(http) @http = http end def succeed @parser = Nokogiri::HTML.parse @http.response super end end def get_document(uri) http = EM::HttpRequest.new(uri).get doc = HtmlDocument.new http http.callback { doc.succeed } http.errback { doc.fail } doc end EM.run do multi = EM::MultiRequest.new [ 'http://www.google.co.jp/', 'http://www.hatena.ne.jp/h/o/g/e', 'http://eagletmt.com/', ].each do |uri| defer = EM::DefaultDeferrable.new multi.add defer doc = get_document uri doc.errback do puts "ng: #{doc.http.error}: #{doc.http.uri}" defer.fail end doc.callback do puts "ok: #{doc.http.uri}: #{doc.http.response_header.status}: #{doc.parser.xpath('//title').inner_text}" m = EM::MultiRequest.new doc.parser.xpath('//a[@href]').each do |a| href = a['href'] if href.start_with? 'http://' doc2 = get_document href doc2.errback do puts " ng: #{doc2.http.error}: #{doc2.http.uri}" end doc2.callback do puts " ok: #{doc2.http.uri}: #{doc2.http.response_header.status}: #{doc2.parser.xpath('//title').inner_text}" end m.add doc2 end end if m.requests.empty? defer.succeed else m.callback do defer.succeed end end end end multi.callback do EM.stop end end