Class: Whenner::Deferred
- Inherits:
-
Object
- Object
- Whenner::Deferred
- Defined in:
- lib/whenner/deferred.rb
Overview
A deferred object is an operation that will eventually resolve to a result value. A deferred can be in three possible states:
- Pending: it has been created but not yet resolved.
- Fulfilled: it has been successfully resolved.
- Rejected: it has been unsuccessfully resolved.
A deferred might transition from pending to fulfilled or rejected, but it will not transition again once resolved (resolved can be either fulfilled or rejected).
When a deferred does resolve, it will trigger any applicable callbacks. You can stack on callbacks on a deferred object before it has been resolved and they will be called later. When you register callbacks on an already resolved deferred, the callback will be called immediately. Note that a callback will only be run once.
When a callback is in the fulfilled state, it has a value that represents its eventual outcome. When it is rejected, it has a reason.
Instance Attribute Summary collapse
-
#promise ⇒ Promise
readonly
A promise for this deferred.
-
#reason ⇒ Object
readonly
The reason the deferred was rejected.
-
#value ⇒ Object
readonly
The value the deferred was resolved with.
Instance Method Summary collapse
-
#always {|value, reason| ... } ⇒ Promise
Register a callback to be run when the deferred is resolved.
-
#done {|value| ... } ⇒ Promise
Register a callback to be run when the deferred is fulfilled.
-
#fail {|reason| ... } ⇒ Promise
Register a callback to be run when the deferred is rejected.
-
#fulfill(value = nil) ⇒ Deferred
Fulfill this promise with an optional value.
-
#fulfilled? ⇒ Boolean
Whether the deferred was successfully resolved.
-
#initialize ⇒ Deferred
constructor
A new instance of Deferred.
-
#pending? ⇒ Boolean
Whether the deferred has not been resolved yet.
-
#reject(reason = nil) ⇒ Deferred
Reject this promise with an optional reason.
-
#rejected? ⇒ Boolean
Whether the deferred was rejected.
-
#resolved? ⇒ Boolean
Whether the deferred was either fulfilled or rejected.
-
#then {|proxy| ... } ⇒ Promise
Register a callback to be run when the deferred is fulfilled.
- #to_promise ⇒ Promise
Constructor Details
#initialize ⇒ Deferred
Returns a new instance of Deferred.
25 26 27 28 29 30 31 |
# File 'lib/whenner/deferred.rb', line 25 def initialize @promise = Promise.new(self) @state = :pending @fulfilled_callbacks = [] @rejected_callbacks = [] @always_callbacks = [] end |
Instance Attribute Details
#promise ⇒ Promise (readonly)
Returns a promise for this deferred.
23 24 25 |
# File 'lib/whenner/deferred.rb', line 23 def promise @promise end |
#reason ⇒ Object
The reason the deferred was rejected.
44 45 46 47 |
# File 'lib/whenner/deferred.rb', line 44 def reason raise UnresolvedError unless resolved? @reason end |
#value ⇒ Object
The value the deferred was resolved with.
36 37 38 39 |
# File 'lib/whenner/deferred.rb', line 36 def value raise UnresolvedError unless resolved? @value end |
Instance Method Details
#always {|value, reason| ... } ⇒ Promise
Register a callback to be run when the deferred is resolved.
161 162 163 164 165 166 |
# File 'lib/whenner/deferred.rb', line 161 def always(&block) cb = Callback.new(block) always_callbacks << cb cb.call(*callback_response) if resolved? cb.promise end |
#done {|value| ... } ⇒ Promise
Register a callback to be run when the deferred is fulfilled.
134 135 136 137 138 139 |
# File 'lib/whenner/deferred.rb', line 134 def done(&block) cb = Callback.new(block) fulfilled_callbacks << cb cb.call(*callback_response) if fulfilled? cb.promise end |
#fail {|reason| ... } ⇒ Promise
Register a callback to be run when the deferred is rejected.
147 148 149 150 151 152 |
# File 'lib/whenner/deferred.rb', line 147 def fail(&block) cb = Callback.new(block) rejected_callbacks << cb cb.call(*callback_response) if rejected? cb.promise end |
#fulfill(value = nil) ⇒ Deferred
Fulfill this promise with an optional value. The value will be stored in
the deferred and passed along to any registered done callbacks.
When fulfilling a deferred twice, nothing happens.
76 77 78 79 80 81 82 83 84 |
# File 'lib/whenner/deferred.rb', line 76 def fulfill(value = nil) raise CannotTransitionError if rejected? return if fulfilled? unless resolved? self.value = value resolve_to(:fulfilled) end self end |
#fulfilled? ⇒ Boolean
Returns whether the deferred was successfully resolved.
55 56 57 |
# File 'lib/whenner/deferred.rb', line 55 def fulfilled? state == :fulfilled end |
#pending? ⇒ Boolean
Returns whether the deferred has not been resolved yet.
50 51 52 |
# File 'lib/whenner/deferred.rb', line 50 def pending? state == :pending end |
#reject(reason = nil) ⇒ Deferred
Reject this promise with an optional reason. The reason will be stored in
the deferred and passed along to any registered fail callbacks.
When rejecting a deferred twice, nothing happens.
93 94 95 96 97 98 99 100 101 |
# File 'lib/whenner/deferred.rb', line 93 def reject(reason = nil) raise CannotTransitionError if fulfilled? return if rejected? unless resolved? self.reason = reason resolve_to(:rejected) end self end |
#rejected? ⇒ Boolean
Returns whether the deferred was rejected.
60 61 62 |
# File 'lib/whenner/deferred.rb', line 60 def rejected? state == :rejected end |
#resolved? ⇒ Boolean
Returns whether the deferred was either fulfilled or rejected.
65 66 67 |
# File 'lib/whenner/deferred.rb', line 65 def resolved? fulfilled? || rejected? end |
#then {|proxy| ... } ⇒ Promise
Register a callback to be run when the deferred is fulfilled.
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/whenner/deferred.rb', line 115 def then Whenner.defer do |d| proxy = DeferredProxy.new(self) yield proxy pdone = done(&proxy.done) pfail = fail(&proxy.fail) pdone.done { |v| d.fulfill(v) } pdone.fail { |v| d.reject(v) } pfail.done { |v| d.reject(v) } pfail.fail { |v| d.reject(v) } end end |
#to_promise ⇒ Promise
104 105 106 |
# File 'lib/whenner/deferred.rb', line 104 def to_promise promise end |