Skip to content

Commit cfd030f

Browse files
committed
Merge pull request #168 from obrok/promise-zip
Add Promise.zip
2 parents 0c74b69 + 5dae1ad commit cfd030f

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

lib/concurrent/promise.rb

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,16 @@ def flat_map(&block)
139139
child
140140
end
141141

142-
# Builds a promise that produces the result of self and others in an Array
142+
# Builds a promise that produces the result of promises in an Array
143143
# and fails if any of them fails.
144144
#
145-
# @param [Array<Promise>] others
145+
# @param [Array<Promise>] promises
146146
#
147-
# @return [Promise]
148-
def zip(*others)
149-
others.reduce(self.then { |x| [x] }) do |p1, p2|
147+
# @return [Promise<Array>]
148+
def self.zip(*promises)
149+
zero = fulfill([], executor: ImmediateExecutor.new)
150+
151+
promises.reduce(zero) do |p1, p2|
150152
p1.flat_map do |results|
151153
p2.then do |next_result|
152154
results << next_result
@@ -155,6 +157,16 @@ def zip(*others)
155157
end
156158
end
157159

160+
# Builds a promise that produces the result of self and others in an Array
161+
# and fails if any of them fails.
162+
#
163+
# @param [Array<Promise>] others
164+
#
165+
# @return [Promise<Array>]
166+
def zip(*others)
167+
self.class.zip(self, *others)
168+
end
169+
158170
protected
159171

160172
def set_pending

spec/concurrent/promise_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,24 @@ module Concurrent
315315
end
316316
end
317317

318+
describe '.zip' do
319+
let(:promise1) { Promise.new(executor: executor) { 1 } }
320+
let(:promise2) { Promise.new(executor: executor) { 2 } }
321+
let(:promise3) { Promise.new(executor: executor) { [3] } }
322+
323+
it 'yields the results as an array' do
324+
composite = Promise.zip(promise1, promise2, promise3).execute.wait
325+
326+
expect(composite.value).to eq([1, 2, [3]])
327+
end
328+
329+
it 'fails if one component fails' do
330+
composite = Promise.zip(promise1, promise2, rejected_subject, promise3).execute.wait
331+
332+
expect(composite).to be_rejected
333+
end
334+
end
335+
318336
context 'fulfillment' do
319337

320338
it 'passes the result of each block to all its children' do

0 commit comments

Comments
 (0)