File tree Expand file tree Collapse file tree 2 files changed +55
-0
lines changed Expand file tree Collapse file tree 2 files changed +55
-0
lines changed Original file line number Diff line number Diff line change @@ -110,6 +110,30 @@ def rescue(&block)
110
110
alias_method :catch , :rescue
111
111
alias_method :on_error , :rescue
112
112
113
+ # Yield the successful result to the block that returns a promise. If that
114
+ # promise is also successful the result is the result of the yielded promise.
115
+ # If either part fails the whole also fails.
116
+ #
117
+ # @example
118
+ # Promise.execute { 1 }.flat_map { |v| Promise.execute { v + 2 } }.value! #=> 3
119
+ #
120
+ # @return [Promise]
121
+ def flat_map ( &block )
122
+ child = Promise . new (
123
+ parent : self
124
+ )
125
+
126
+ on_error { |e | child . on_reject ( e ) }
127
+ on_success do |result1 |
128
+ inner = block . call ( result1 )
129
+ inner . execute
130
+ inner . on_success { |result2 | child . on_fulfill ( result2 ) }
131
+ inner . on_error { |e | child . on_reject ( e ) }
132
+ end
133
+
134
+ child
135
+ end
136
+
113
137
protected
114
138
115
139
def set_pending
Original file line number Diff line number Diff line change @@ -260,6 +260,37 @@ module Concurrent
260
260
end
261
261
end
262
262
263
+ describe '#flat_map' do
264
+
265
+ it 'returns a promise' do
266
+ child = empty_root . flat_map { nil }
267
+ expect ( child ) . to be_a Promise
268
+ expect ( child ) . not_to be empty_root
269
+ end
270
+
271
+ it 'succeeds if both promises succeed' do
272
+ child = Promise . new ( executor : executor ) { 1 } .
273
+ flat_map { |v | Promise . new ( executor : executor ) { v + 10 } } . execute
274
+ sleep 0.1
275
+ expect ( child . value! ) . to eq ( 11 )
276
+ end
277
+
278
+ it 'fails if the left promise fails' do
279
+ child = Promise . new ( executor : executor ) { fail } .
280
+ flat_map { |v | Promise . new ( executor : executor ) { v + 10 } } . execute
281
+ sleep 0.1
282
+ expect ( child ) . to be_rejected
283
+ end
284
+
285
+ it 'fails if the right promise fails' do
286
+ child = Promise . new ( executor : executor ) { 1 } .
287
+ flat_map { |v | Promise . new ( executor : executor ) { fail } } . execute
288
+ sleep 0.1
289
+ expect ( child ) . to be_rejected
290
+ end
291
+
292
+ end
293
+
263
294
context 'fulfillment' do
264
295
265
296
it 'passes the result of each block to all its children' do
You can’t perform that action at this time.
0 commit comments