Class: Promise

Inherits:
Object show all
Defined in:
lib/hyper-operation/promise.rb

Direct Known Subclasses

Trace, When

Defined Under Namespace

Classes: Trace, When

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(action = {}) ⇒ Promise



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/hyper-operation/promise.rb', line 16

def initialize(action = {})
  @action = action

  @realized  = false
  @exception = false
  @value     = nil
  @error     = nil
  @delayed   = false

  @prev = nil
  @next = []
end

Instance Attribute Details

#errorObject (readonly)

Returns the value of attribute error.



14
15
16
# File 'lib/hyper-operation/promise.rb', line 14

def error
  @error
end

#nextObject (readonly)

Returns the value of attribute next.



14
15
16
# File 'lib/hyper-operation/promise.rb', line 14

def next
  @next
end

#prevObject (readonly)

Returns the value of attribute prev.



14
15
16
# File 'lib/hyper-operation/promise.rb', line 14

def prev
  @prev
end

Class Method Details

.error(value) ⇒ Object



6
7
8
# File 'lib/hyper-operation/promise.rb', line 6

def self.error(value)
  new.reject(value)
end

.value(value) ⇒ Object



2
3
4
# File 'lib/hyper-operation/promise.rb', line 2

def self.value(value)
  new.resolve(value)
end

.when(*promises) ⇒ Object



10
11
12
# File 'lib/hyper-operation/promise.rb', line 10

def self.when(*promises)
  When.new(promises)
end

Instance Method Details

#<<(promise) ⇒ Object



72
73
74
75
76
# File 'lib/hyper-operation/promise.rb', line 72

def <<(promise)
  @prev = promise

  self
end

#>>(promise) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/hyper-operation/promise.rb', line 78

def >>(promise)
  @next << promise

  if exception?
    promise.reject(@delayed[0])
  elsif resolved?
    promise.resolve(@delayed ? @delayed[0] : value)
  elsif rejected?
    if !@action.has_key?(:failure) || Promise === (@delayed ? @delayed[0] : @error)
      promise.reject(@delayed ? @delayed[0] : error)
    elsif promise.action.include?(:always)
      promise.reject(@delayed ? @delayed[0] : error)
    end
  end

  self
end

#^(promise) ⇒ Object



65
66
67
68
69
70
# File 'lib/hyper-operation/promise.rb', line 65

def ^(promise)
  promise << self
  self    >> promise

  promise
end

#act?Boolean



37
38
39
# File 'lib/hyper-operation/promise.rb', line 37

def act?
  @action.has_key?(:success) || @action.has_key?(:always)
end

#actionObject



41
42
43
# File 'lib/hyper-operation/promise.rb', line 41

def action
  @action.keys
end

#always(&block) ⇒ Object Also known as: finally, ensure



198
199
200
# File 'lib/hyper-operation/promise.rb', line 198

def always(&block)
  self ^ Promise.new(always: block)
end

#always!(&block) ⇒ Object Also known as: finally!, ensure!



202
203
204
205
# File 'lib/hyper-operation/promise.rb', line 202

def always!(&block)
  there_can_be_only_one!
  always(&block)
end

#exception!(error) ⇒ Object



166
167
168
169
170
# File 'lib/hyper-operation/promise.rb', line 166

def exception!(error)
  @exception = true

  reject!(error)
end

#exception?Boolean



45
46
47
# File 'lib/hyper-operation/promise.rb', line 45

def exception?
  @exception
end

#fail(&block) ⇒ Object Also known as: rescue, catch



184
185
186
# File 'lib/hyper-operation/promise.rb', line 184

def fail(&block)
  self ^ Promise.new(failure: block)
end

#fail!(&block) ⇒ Object Also known as: rescue!, catch!



188
189
190
191
# File 'lib/hyper-operation/promise.rb', line 188

def fail!(&block)
  there_can_be_only_one!
  fail(&block)
end

#inspectObject



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/hyper-operation/promise.rb', line 227

def inspect
  result = "#<#{self.class}(#{object_id})"

  if @next.any?
    result += " >> #{@next.inspect}"
  end

  if realized?
    result += ": #{(@value || @error).inspect}>"
  else
    result += ">"
  end

  result
end

#pending?Boolean



61
62
63
# File 'lib/hyper-operation/promise.rb', line 61

def pending?
  !realized?
end

#realized?Boolean



49
50
51
# File 'lib/hyper-operation/promise.rb', line 49

def realized?
  !!@realized
end

#reject(value = nil) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/hyper-operation/promise.rb', line 129

def reject(value = nil)
  if realized?
    raise ArgumentError, 'the promise has already been realized'
  end

  if Promise === value
    return (value << @prev) ^ self
  end

  begin
    if block = @action[:failure] || @action[:always]
      value = block.call(value)
    end

    if @action.has_key?(:always)
      resolve!(value)
    else
      reject!(value)
    end
  rescue Exception => e
    exception!(e)
  end

  self
end

#reject!(value) ⇒ Object



155
156
157
158
159
160
161
162
163
164
# File 'lib/hyper-operation/promise.rb', line 155

def reject!(value)
  @realized = :reject
  @error    = value

  if @next.any?
    @next.each { |p| p.reject(value) }
  else
    @delayed = [value]
  end
end

#rejected?Boolean



57
58
59
# File 'lib/hyper-operation/promise.rb', line 57

def rejected?
  @realized == :reject
end

#resolve(value = nil) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/hyper-operation/promise.rb', line 96

def resolve(value = nil)
  if realized?
    raise ArgumentError, 'the promise has already been realized'
  end

  if Promise === value
    return (value << @prev) ^ self
  end

  begin
    if block = @action[:success] || @action[:always]
      value = block.call(value)
    end

    resolve!(value)
  rescue Exception => e
    exception!(e)
  end

  self
end

#resolve!(value) ⇒ Object



118
119
120
121
122
123
124
125
126
127
# File 'lib/hyper-operation/promise.rb', line 118

def resolve!(value)
  @realized = :resolve
  @value    = value

  if @next.any?
    @next.each { |p| p.resolve(value) }
  else
    @delayed = [value]
  end
end

#resolved?Boolean



53
54
55
# File 'lib/hyper-operation/promise.rb', line 53

def resolved?
  @realized == :resolve
end

#then(&block) ⇒ Object Also known as: do



172
173
174
# File 'lib/hyper-operation/promise.rb', line 172

def then(&block)
  self ^ Promise.new(success: block)
end

#then!(&block) ⇒ Object Also known as: do!



176
177
178
179
# File 'lib/hyper-operation/promise.rb', line 176

def then!(&block)
  there_can_be_only_one!
  self.then(&block)
end

#there_can_be_only_one!Object



221
222
223
224
225
# File 'lib/hyper-operation/promise.rb', line 221

def there_can_be_only_one!
  if @next.any?
    raise ArgumentError, 'a promise has already been chained'
  end
end

#trace(depth = nil, &block) ⇒ Object



212
213
214
# File 'lib/hyper-operation/promise.rb', line 212

def trace(depth = nil, &block)
  self ^ Trace.new(depth, block)
end

#trace!(*args, &block) ⇒ Object



216
217
218
219
# File 'lib/hyper-operation/promise.rb', line 216

def trace!(*args, &block)
  there_can_be_only_one!
  trace(*args, &block)
end

#valueObject



29
30
31
32
33
34
35
# File 'lib/hyper-operation/promise.rb', line 29

def value
  if Promise === @value
    @value.value
  else
    @value
  end
end