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 endDefaultDeferrable 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