Skip to content

Commit 24f6997

Browse files
committedApr 26, 2015
Fix Promise#always
1 parent 5fca5b1 commit 24f6997

File tree

3 files changed

+86
-36
lines changed

3 files changed

+86
-36
lines changed
 
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
require 'promise'
2+
3+
describe 'Promise#always' do
4+
it 'calls the block when it was resolved' do
5+
x = 42
6+
Promise.value(23).then { |v| x = v }.always { |v| x = 2 }
7+
x.should == 2
8+
end
9+
10+
it 'calls the block when it was rejected' do
11+
x = 42
12+
Promise.error(23).rescue { |v| x = v }.always { |v| x = 2 }
13+
x.should == 2
14+
end
15+
16+
it 'acts as resolved' do
17+
x = 42
18+
Promise.error(23).rescue { |v| x = v }.always { x = 2 }.then { x = 3 }
19+
x.should == 3
20+
end
21+
22+
it 'raises an exception when the promise has already been chained' do
23+
p = Promise.value(2)
24+
p.then {}
25+
26+
proc {
27+
p.always {}
28+
}.should raise_error(ArgumentError)
29+
end
30+
end

‎spec/opal/stdlib/promise/trace_spec.rb

+8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121
x.should == 6
2222
end
2323

24+
it 'includes the first value' do
25+
x = 42
26+
27+
Promise.value(1).trace { |a| x = a }
28+
29+
x.should == 1
30+
end
31+
2432
it 'works after a when' do
2533
x = 42
2634

‎stdlib/promise.rb

+48-36
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,12 @@ def self.when(*promises)
110110
When.new(promises)
111111
end
112112

113-
attr_reader :value, :error, :prev, :next
113+
attr_reader :error, :prev, :next
114114

115-
def initialize(success = nil, failure = nil)
116-
@success = success
117-
@failure = failure
115+
def initialize(action = {})
116+
@action = action
118117

119-
@realized = nil
118+
@realized = false
120119
@exception = false
121120
@value = nil
122121
@error = nil
@@ -126,16 +125,28 @@ def initialize(success = nil, failure = nil)
126125
@next = nil
127126
end
128127

128+
def value
129+
if Promise === @value
130+
@value.value
131+
else
132+
@value
133+
end
134+
end
135+
129136
def act?
130-
@success != nil
137+
@action.has_key?(:success) || @action.has_key?(:always)
138+
end
139+
140+
def action
141+
@action.keys
131142
end
132143

133144
def exception?
134145
@exception
135146
end
136147

137148
def realized?
138-
@realized != nil
149+
!!@realized
139150
end
140151

141152
def resolved?
@@ -166,8 +177,12 @@ def >>(promise)
166177
promise.reject(@delayed[0])
167178
elsif resolved?
168179
promise.resolve(@delayed ? @delayed[0] : value)
169-
elsif rejected? && (!@failure || Promise === (@delayed ? @delayed[0] : @error))
170-
promise.reject(@delayed ? @delayed[0] : error)
180+
elsif rejected?
181+
if !@action.has_key?(:failure) || Promise === (@delayed ? @delayed[0] : @error)
182+
promise.reject(@delayed ? @delayed[0] : error)
183+
elsif promise.action.include?(:always)
184+
promise.reject(@delayed ? @delayed[0] : error)
185+
end
171186
end
172187

173188
self
@@ -179,17 +194,12 @@ def resolve(value = nil)
179194
end
180195

181196
if Promise === value
182-
value << @prev
183-
184-
return value ^ self
197+
return (value << @prev) ^ self
185198
end
186199

187-
@realized = :resolve
188-
@value = value
189-
190200
begin
191-
if @success
192-
value = @success.call(value)
201+
if block = @action[:success] || @action[:always]
202+
value = block.call(value)
193203
end
194204

195205
resolve!(value)
@@ -201,6 +211,9 @@ def resolve(value = nil)
201211
end
202212

203213
def resolve!(value)
214+
@realized = :resolve
215+
@value = value
216+
204217
if @next
205218
@next.resolve(value)
206219
else
@@ -214,21 +227,16 @@ def reject(value = nil)
214227
end
215228

216229
if Promise === value
217-
value << @prev
218-
219-
return value ^ self
230+
return (value << @prev) ^ self
220231
end
221232

222-
@realized = :reject
223-
@error = value
224-
225233
begin
226-
if @failure
227-
value = @failure.call(value)
234+
if block = @action[:failure] || @action[:always]
235+
value = block.call(value)
236+
end
228237

229-
if Promise === value
230-
reject!(value)
231-
end
238+
if @action.has_key?(:always)
239+
resolve!(value)
232240
else
233241
reject!(value)
234242
end
@@ -240,6 +248,9 @@ def reject(value = nil)
240248
end
241249

242250
def reject!(value)
251+
@realized = :reject
252+
@error = value
253+
243254
if @next
244255
@next.reject(value)
245256
else
@@ -258,7 +269,7 @@ def then(&block)
258269
raise ArgumentError, 'a promise has already been chained'
259270
end
260271

261-
self ^ Promise.new(block)
272+
self ^ Promise.new(success: block)
262273
end
263274

264275
alias do then
@@ -268,7 +279,7 @@ def fail(&block)
268279
raise ArgumentError, 'a promise has already been chained'
269280
end
270281

271-
self ^ Promise.new(nil, block)
282+
self ^ Promise.new(failure: block)
272283
end
273284

274285
alias rescue fail
@@ -279,7 +290,7 @@ def always(&block)
279290
raise ArgumentError, 'a promise has already been chained'
280291
end
281292

282-
self ^ Promise.new(block, block)
293+
self ^ Promise.new(always: block)
283294
end
284295

285296
alias finally always
@@ -311,11 +322,11 @@ def inspect
311322

312323
class Trace < self
313324
def self.it(promise)
314-
unless promise.realized?
315-
raise ArgumentError, "the promise hasn't been realized"
316-
end
325+
current = []
317326

318-
current = promise.act? ? [promise.value] : []
327+
if promise.act? || promise.prev.nil?
328+
current.push(promise.value)
329+
end
319330

320331
if prev = promise.prev
321332
current.concat(it(prev))
@@ -327,8 +338,9 @@ def self.it(promise)
327338
def initialize(depth, block)
328339
@depth = depth
329340

330-
super -> {
341+
super success: -> {
331342
trace = Trace.it(self).reverse
343+
trace.pop
332344

333345
if depth && depth <= trace.length
334346
trace.shift(trace.length - depth)

0 commit comments

Comments
 (0)