From 8afabb7aeedaf5296b5780a5227cf43fb390af1c Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Mon, 17 Jan 2022 15:24:06 +0100 Subject: [PATCH] Enforce always passing promise to race function The race function has always supported passing an empty array of promises/values into it. And then defaulted to the behavior of returning an ever waiting promise. While this makes sense from a mathematical perspective, it doesn't from a developers' perspective. To enforce always having to pass in a promise, the first argument is now required, and any following promises are accepted using a variadic function argument. --- src/functions.php | 17 +++++--------- tests/FunctionRaceTest.php | 46 +++++--------------------------------- 2 files changed, 11 insertions(+), 52 deletions(-) diff --git a/src/functions.php b/src/functions.php index df50eb33..e3df29a4 100644 --- a/src/functions.php +++ b/src/functions.php @@ -83,22 +83,17 @@ function all(array $promisesOrValues): PromiseInterface * Initiates a competitive race that allows one winner. Returns a promise which is * resolved in the same way the first settled promise resolves. * - * The returned promise will become **infinitely pending** if `$promisesOrValues` - * contains 0 items. - * - * @param array $promisesOrValues + * @param PromiseInterface $promise + * @param array $promises * @return PromiseInterface */ -function race(array $promisesOrValues): PromiseInterface +function race(PromiseInterface $promise, PromiseInterface ...$promises): PromiseInterface { - if (!$promisesOrValues) { - return new Promise(function (): void {}); - } - + $promises[] = $promise; $cancellationQueue = new Internal\CancellationQueue(); - return new Promise(function ($resolve, $reject) use ($promisesOrValues, $cancellationQueue): void { - foreach ($promisesOrValues as $promiseOrValue) { + return new Promise(function ($resolve, $reject) use ($promises, $cancellationQueue): void { + foreach ($promises as $promiseOrValue) { $cancellationQueue->enqueue($promiseOrValue); resolve($promiseOrValue) diff --git a/tests/FunctionRaceTest.php b/tests/FunctionRaceTest.php index 83649173..b8325d06 100644 --- a/tests/FunctionRaceTest.php +++ b/tests/FunctionRaceTest.php @@ -6,28 +6,6 @@ class FunctionRaceTest extends TestCase { - /** @test */ - public function shouldReturnForeverPendingPromiseForEmptyInput() - { - race( - [] - )->then($this->expectCallableNever(), $this->expectCallableNever()); - } - - /** @test */ - public function shouldResolveValuesArray() - { - $mock = $this->createCallableMock(); - $mock - ->expects(self::once()) - ->method('__invoke') - ->with(self::identicalTo(1)); - - race( - [1, 2, 3] - )->then($mock); - } - /** @test */ public function shouldResolvePromisesArray() { @@ -42,7 +20,7 @@ public function shouldResolvePromisesArray() $d3 = new Deferred(); race( - [$d1->promise(), $d2->promise(), $d3->promise()] + $d1->promise(), $d2->promise(), $d3->promise() )->then($mock); $d2->resolve(2); @@ -51,20 +29,6 @@ public function shouldResolvePromisesArray() $d3->resolve(3); } - /** @test */ - public function shouldResolveSparseArrayInput() - { - $mock = $this->createCallableMock(); - $mock - ->expects(self::once()) - ->method('__invoke') - ->with(self::identicalTo(null)); - - race( - [null, 1, null, 2, 3] - )->then($mock); - } - /** @test */ public function shouldRejectIfFirstSettledPromiseRejects() { @@ -81,7 +45,7 @@ public function shouldRejectIfFirstSettledPromiseRejects() $d3 = new Deferred(); race( - [$d1->promise(), $d2->promise(), $d3->promise()] + $d1->promise(), $d2->promise(), $d3->promise() )->then($this->expectCallableNever(), $mock); $d2->reject($exception); @@ -96,7 +60,7 @@ public function shouldCancelInputArrayPromises() $promise1 = new Promise(function () {}, $this->expectCallableOnce()); $promise2 = new Promise(function () {}, $this->expectCallableOnce()); - race([$promise1, $promise2])->cancel(); + race($promise1, $promise2)->cancel(); } /** @test */ @@ -107,7 +71,7 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseFulfill $promise2 = new Promise(function () {}, $this->expectCallableNever()); - race([$deferred->promise(), $promise2])->cancel(); + race($deferred->promise(), $promise2)->cancel(); } /** @test */ @@ -118,6 +82,6 @@ public function shouldNotCancelOtherPendingInputArrayPromisesIfOnePromiseRejects $promise2 = new Promise(function () {}, $this->expectCallableNever()); - race([$deferred->promise(), $promise2])->cancel(); + race($deferred->promise(), $promise2)->cancel(); } }