diff --git a/lib/concurrent/promise.rb b/lib/concurrent/promise.rb index 77a658bbc..fa6f1b1f3 100644 --- a/lib/concurrent/promise.rb +++ b/lib/concurrent/promise.rb @@ -307,7 +307,16 @@ def self.execute(opts = {}, &block) # @yield The block operation to be performed asynchronously. # # @return [Promise] the new promise - def then(rescuer = nil, executor = @executor, &block) + def then(*args, &block) + if args.last.is_a?(::Hash) + executor = args.pop[:executor] + rescuer = args.first + else + rescuer, executor = args + end + + executor ||= @executor + raise ArgumentError.new('rescuers and block are both missing') if rescuer.nil? && !block_given? block = Proc.new { |result| result } unless block_given? child = Promise.new( diff --git a/spec/concurrent/promise_spec.rb b/spec/concurrent/promise_spec.rb index a4b5bcb92..56b9de07d 100644 --- a/spec/concurrent/promise_spec.rb +++ b/spec/concurrent/promise_spec.rb @@ -225,6 +225,13 @@ def get_ivar_from_args(opts) expect(child).not_to be empty_root expect(child.instance_variable_get(:@executor)).to be(new_executor) end + + it 'supports setting the executor using a named parameter' do + new_executor = Concurrent::SingleThreadExecutor.new + child = empty_root.then(executor: new_executor) { nil } + expect(child.instance_variable_get(:@executor)).to be(new_executor) + end + it 'should have block or rescuers' do expect { empty_root.then }.to raise_error(ArgumentError) end