Skip to content

Commit 907b3a4

Browse files
committed
feature: throw rejections that aren't handled
closes #63
1 parent ccc1927 commit 907b3a4

File tree

2 files changed

+13
-35
lines changed

2 files changed

+13
-35
lines changed

src/Promise.php

+12-34
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ class Promise implements PromiseInterface {
1515
private array $chain;
1616
/** @var CatchChain[] */
1717
private array $uncalledCatchChain;
18+
/** @var Throwable[] */
19+
private array $handledRejections;
1820
/** @var callable */
1921
private $executor;
20-
private bool $completed;
2122

2223
public function __construct(callable $executor) {
23-
$this->completed = false;
2424
$this->chain = [];
2525
$this->uncalledCatchChain = [];
26+
$this->handledRejections = [];
2627

2728
$this->executor = $executor;
2829
$this->callExecutor();
@@ -123,7 +124,8 @@ private function reset():void {
123124
}
124125

125126
private function tryComplete():void {
126-
if(empty($this->chain) && $this->getState() === PromiseState::PENDING) {
127+
if(empty($this->chain)) {
128+
$this->throwUnhandledRejection();
127129
return;
128130
}
129131
if($this->getState() !== PromiseState::PENDING) {
@@ -145,10 +147,7 @@ function(Chainable $a, Chainable $b) {
145147
return 0;
146148
}
147149
);
148-
$handledRejections = [];
149150

150-
$emptyChain = empty($this->chain);
151-
$originalChain = $this->chain;
152151
while($this->getState() !== PromiseState::PENDING) {
153152
$chainItem = $this->getNextChainItem();
154153
if(!$chainItem) {
@@ -160,17 +159,15 @@ function(Chainable $a, Chainable $b) {
160159
}
161160
elseif($chainItem instanceof CatchChain) {
162161
if($handled = $this->handleCatch($chainItem)) {
163-
array_push($handledRejections, $handled);
162+
array_push($this->handledRejections, $handled);
164163
}
165164
}
166165
elseif($chainItem instanceof FinallyChain) {
167166
$this->handleFinally($chainItem);
168167
}
169168
}
170169

171-
$this->handleCatches($originalChain, $emptyChain, $handledRejections);
172-
173-
$this->completed = true;
170+
$this->throwUnhandledRejection();
174171
}
175172

176173
private function getNextChainItem():?Chainable {
@@ -200,7 +197,8 @@ private function handleThen(ThenChain $then):void {
200197

201198
private function handleCatch(CatchChain $catch):?Throwable {
202199
if($this->getState() !== PromiseState::REJECTED) {
203-
// TODO: This is where #52 can be implemented.
200+
// TODO: This is where #52 can be implemented
201+
// see: (https://github.com/PhpGt/Promise/issues/52)
204202
array_push($this->uncalledCatchChain, $catch);
205203
return null;
206204
}
@@ -244,29 +242,9 @@ private function handleFinally(FinallyChain $finally):void {
244242
}
245243
}
246244

247-
/**
248-
* @param array<Chainable> $chain
249-
* @param bool $emptyChain
250-
* @param array<Throwable> $handledRejections
251-
*/
252-
protected function handleCatches(
253-
array $chain,
254-
bool $emptyChain,
255-
array $handledRejections,
256-
):void {
257-
if ($this->getState() === PromiseState::REJECTED) {
258-
$hasCatch = false;
259-
foreach ($chain as $chainItem) {
260-
if ($chainItem instanceof CatchChain) {
261-
$hasCatch = true;
262-
}
263-
}
264-
265-
if (!$hasCatch) {
266-
throw $this->rejectedReason;
267-
}
268-
269-
if (!$emptyChain && !in_array($this->rejectedReason, $handledRejections)) {
245+
protected function throwUnhandledRejection():void {
246+
if($this->getState() === PromiseState::REJECTED) {
247+
if(!in_array($this->rejectedReason, $this->handledRejections)) {
270248
throw $this->rejectedReason;
271249
}
272250
}

test/phpunit/PromiseTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ public function testPromiseRejectsIfResolvedWithItself() {
5555
$actualMessage = $reason->getMessage();
5656
});
5757

58-
self::expectExceptionMessage("A Promise must not be resolved with another Promise.");
5958
$promiseContainer->resolve($sut);
6059
self::assertEquals(0, $onResolvedCallCount);
60+
self::assertSame("A Promise must not be resolved with another Promise.", $actualMessage);
6161
}
6262

6363
public function testRejectWithException() {

0 commit comments

Comments
 (0)