Event::Machine’s Deferrable borrows heavily from the deferred object in Python’s Twisted event-handling framework. Here’s a minimal example that illustrates Deferrable:
require 'eventmachine'
class MyClass
include EM::Deferrable
def print_value x
puts "MyClass instance received #{x}"
end
end
EM.run {
df = MyClass.new
df.callback {|x|
df.print_value(x)
EM.stop
}
EM::Timer.new(2) {
df.set_deferred_status :succeeded, 100
}
}
This program will spin for two seconds, print out the string
MyClass instance received 100 and then exit.
The Deferrable pattern allows you to specify any number of Ruby code blocks (callbacks or errbacks) that will be executed at some future time when the status of the Deferrable object changes.
How might that be useful?
set_deferred_status method on the Deferrable
object, passing either a success or failure status, and an arbitrary
number of parameters (which might include the data you received
from the other server).
set_deferred_status, the Deferrable will IMMEDIATELY
execute all of its callbacks or errbacks in the order in which they
were added to the Deferrable.
Deferrable#set_deferred_status takes :succeeded
or :failed
as its first argument. (This determines whether the object will
call its callbacks or its errbacks.) set_deferred_status also takes
zero or more additional parameters, that will in turn be passed as
parameters to the callbacks or errbacks.
set_deferred_status ONCE on a Deferrable
object. A call to set_deferred_status will not return until all of
the associated callbacks or errbacks have been called. If you add
callbacks or errbacks AFTER making a call to set_deferred_status,
those additional callbacks or errbacks will execute IMMEDIATELY.
Any given callback or errback will be executed AT MOST once.
set_deferred_status AGAIN, during the
execution a callback or errback. This makes it possible to change
the parameters which will be sent to the callbacks or errbacks
farther down the chain, enabling some extremely elegant use-cases.
You can transform the data returned from a deferred operation in
arbitrary ways as needed by subsequent users, without changing any
of the code that generated the original data.
set_deferred_status will not return until all of
the associated callbacks or errbacks have been called. If you add
callbacks or errbacks AFTER making a call to set_deferred_status,
those additional callbacks or errbacks will execute IMMEDIATELY.
[~/ruby/eventmachine/deferrable(master)]$ cat defaultdeferrable.rb
require 'eventmachine'
EM.run do
df = EM::DefaultDeferrable.new
df.callback do |x|
puts "got #{x}"
end
df.callback do |x|
EM.stop
end
EM.add_timer(1) do
df.set_deferred_status :succeeded, "monkeys"
end
end
DefaultDeferrable is an otherwise empty class that includes Deferrable.
This is useful when you just need to return a Deferrable object as a way of communicating deferred status to some other part of a program.
[~/ruby/eventmachine/deferrable(master)]$ ruby defaultdeferrable.rb got monkeys
Casiano Rodriguez León 2015-01-07