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)
110110 alias_method :catch , :rescue
111111 alias_method :on_error , :rescue
112112
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+
113137 protected
114138
115139 def set_pending
Original file line number Diff line number Diff line change @@ -260,6 +260,37 @@ module Concurrent
260260 end
261261 end
262262
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+
263294 context 'fulfillment' do
264295
265296 it 'passes the result of each block to all its children' do
You can’t perform that action at this time.
0 commit comments