Skip to content

Commit 84322e6

Browse files
committed
Add catch() and finally(), deprecate otherwise() and always()
1 parent 9647500 commit 84322e6

12 files changed

+590
-76
lines changed

README.md

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ Table of Contents
2929
* [PromiseInterface](#promiseinterface)
3030
* [PromiseInterface::then()](#promiseinterfacethen)
3131
* [PromiseInterface::done()](#promiseinterfacedone)
32-
* [PromiseInterface::otherwise()](#promiseinterfaceotherwise)
33-
* [PromiseInterface::always()](#promiseinterfacealways)
32+
* [PromiseInterface::catch()](#promiseinterfacecatch)
33+
* [PromiseInterface::finally()](#promiseinterfacefinally)
3434
* [PromiseInterface::cancel()](#promiseinterfacecancel)
35+
* [~~PromiseInterface::otherwise()~~](#promiseinterfaceotherwise)
36+
* [~~PromiseInterface::always()~~](#promiseinterfacealways)
3537
* [Promise](#promise-2)
3638
* [Functions](#functions)
3739
* [resolve()](#resolve)
@@ -206,10 +208,10 @@ Since the purpose of `done()` is consumption rather than transformation,
206208
* [PromiseInterface::then()](#promiseinterfacethen)
207209
* [done() vs. then()](#done-vs-then)
208210

209-
#### PromiseInterface::otherwise()
211+
#### PromiseInterface::catch()
210212

211213
```php
212-
$promise->otherwise(callable $onRejected);
214+
$promise->catch(callable $onRejected);
213215
```
214216

215217
Registers a rejection handler for promise. It is a shortcut for:
@@ -223,19 +225,19 @@ only specific errors.
223225

224226
```php
225227
$promise
226-
->otherwise(function (\RuntimeException $reason) {
228+
->catch(function (\RuntimeException $reason) {
227229
// Only catch \RuntimeException instances
228230
// All other types of errors will propagate automatically
229231
})
230-
->otherwise(function (\Throwable $reason) {
232+
->catch(function (\Throwable $reason) {
231233
// Catch other errors
232234
});
233235
```
234236

235-
#### PromiseInterface::always()
237+
#### PromiseInterface::finally()
236238

237239
```php
238-
$newPromise = $promise->always(callable $onFulfilledOrRejected);
240+
$newPromise = $promise->finally(callable $onFulfilledOrRejected);
239241
```
240242

241243
Allows you to execute "cleanup" type tasks in a promise chain.
@@ -254,15 +256,15 @@ when the promise is either fulfilled or rejected.
254256
rejected promise, `$newPromise` will reject with the thrown exception or
255257
rejected promise's reason.
256258

257-
`always()` behaves similarly to the synchronous finally statement. When combined
258-
with `otherwise()`, `always()` allows you to write code that is similar to the familiar
259+
`finally()` behaves similarly to the synchronous finally statement. When combined
260+
with `catch()`, `finally()` allows you to write code that is similar to the familiar
259261
synchronous catch/finally pair.
260262

261263
Consider the following synchronous code:
262264

263265
```php
264266
try {
265-
return doSomething();
267+
return doSomething();
266268
} catch (\Throwable $e) {
267269
return handleError($e);
268270
} finally {
@@ -275,8 +277,8 @@ written:
275277

276278
```php
277279
return doSomething()
278-
->otherwise('handleError')
279-
->always('cleanup');
280+
->catch('handleError')
281+
->finally('cleanup');
280282
```
281283

282284
#### PromiseInterface::cancel()
@@ -291,6 +293,32 @@ further interest in the results of the operation.
291293
Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
292294
a promise has no effect.
293295

296+
#### ~~PromiseInterface::otherwise()~~
297+
298+
> Deprecated since v3.0.0, see [`catch()`](#promiseinterfacecatch) instead.
299+
300+
The `otherwise()` method registers a rejection handler for a promise.
301+
302+
This method continues to exist only for BC reasons and to ease upgrading
303+
between versions. It is an alias for:
304+
305+
```php
306+
$promise->catch($onRejected);
307+
```
308+
309+
#### ~~PromiseInterface::always()~~
310+
311+
> Deprecated since v3.0.0, see [`finally()`](#promiseinterfacefinally) instead.
312+
313+
The `always()` method allows you to execute "cleanup" type tasks in a promise chain.
314+
315+
This method continues to exist only for BC reasons and to ease upgrading
316+
between versions. It is an alias for:
317+
318+
```php
319+
$promise->finally($onFulfilledOrRejected);
320+
```
321+
294322
### Promise
295323

296324
Creates a promise whose state is controlled by the functions passed to
@@ -559,17 +587,17 @@ $deferred->promise()
559587
->then(function ($x) {
560588
throw new \Exception($x + 1);
561589
})
562-
->otherwise(function (\Exception $x) {
590+
->catch(function (\Exception $x) {
563591
// Propagate the rejection
564592
throw $x;
565593
})
566-
->otherwise(function (\Exception $x) {
594+
->catch(function (\Exception $x) {
567595
// Can also propagate by returning another rejection
568596
return React\Promise\reject(
569597
new \Exception($x->getMessage() + 1)
570598
);
571599
})
572-
->otherwise(function ($x) {
600+
->catch(function ($x) {
573601
echo 'Reject ' . $x->getMessage(); // 3
574602
});
575603

@@ -591,7 +619,7 @@ $deferred->promise()
591619
->then(function ($x) {
592620
throw new \Exception($x + 1);
593621
})
594-
->otherwise(function (\Exception $x) {
622+
->catch(function (\Exception $x) {
595623
// Handle the rejection, and don't propagate.
596624
// This is like catch without a rethrow
597625
return $x->getMessage() + 1;

src/Internal/FulfilledPromise.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ public function done(callable $onFulfilled = null, callable $onRejected = null):
6060
});
6161
}
6262

63-
public function otherwise(callable $onRejected): PromiseInterface
63+
public function catch(callable $onRejected): PromiseInterface
6464
{
6565
return $this;
6666
}
6767

68-
public function always(callable $onFulfilledOrRejected): PromiseInterface
68+
public function finally(callable $onFulfilledOrRejected): PromiseInterface
6969
{
7070
return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface {
7171
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
@@ -77,4 +77,22 @@ public function always(callable $onFulfilledOrRejected): PromiseInterface
7777
public function cancel(): void
7878
{
7979
}
80+
81+
/**
82+
* @deprecated 3.0.0 Use `catch()` instead
83+
* @see self::catch()
84+
*/
85+
public function otherwise(callable $onRejected): PromiseInterface
86+
{
87+
return $this->catch($onRejected);
88+
}
89+
90+
/**
91+
* @deprecated 3.0.0 Use `finally()` instead
92+
* @see self::finally()
93+
*/
94+
public function always(callable $onFulfilledOrRejected): PromiseInterface
95+
{
96+
return $this->finally($onFulfilledOrRejected);
97+
}
8098
}

src/Internal/RejectedPromise.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function done(callable $onFulfilled = null, callable $onRejected = null):
6161
});
6262
}
6363

64-
public function otherwise(callable $onRejected): PromiseInterface
64+
public function catch(callable $onRejected): PromiseInterface
6565
{
6666
if (!_checkTypehint($onRejected, $this->reason)) {
6767
return $this;
@@ -70,7 +70,7 @@ public function otherwise(callable $onRejected): PromiseInterface
7070
return $this->then(null, $onRejected);
7171
}
7272

73-
public function always(callable $onFulfilledOrRejected): PromiseInterface
73+
public function finally(callable $onFulfilledOrRejected): PromiseInterface
7474
{
7575
return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
7676
return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface {
@@ -82,4 +82,22 @@ public function always(callable $onFulfilledOrRejected): PromiseInterface
8282
public function cancel(): void
8383
{
8484
}
85+
86+
/**
87+
* @deprecated 3.0.0 Use `catch()` instead
88+
* @see self::catch()
89+
*/
90+
public function otherwise(callable $onRejected): PromiseInterface
91+
{
92+
return $this->catch($onRejected);
93+
}
94+
95+
/**
96+
* @deprecated 3.0.0 Use `always()` instead
97+
* @see self::always()
98+
*/
99+
public function always(callable $onFulfilledOrRejected): PromiseInterface
100+
{
101+
return $this->finally($onFulfilledOrRejected);
102+
}
85103
}

src/Promise.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function done(callable $onFulfilled = null, callable $onRejected = null):
7070
};
7171
}
7272

73-
public function otherwise(callable $onRejected): PromiseInterface
73+
public function catch(callable $onRejected): PromiseInterface
7474
{
7575
return $this->then(null, static function ($reason) use ($onRejected) {
7676
if (!_checkTypehint($onRejected, $reason)) {
@@ -81,7 +81,7 @@ public function otherwise(callable $onRejected): PromiseInterface
8181
});
8282
}
8383

84-
public function always(callable $onFulfilledOrRejected): PromiseInterface
84+
public function finally(callable $onFulfilledOrRejected): PromiseInterface
8585
{
8686
return $this->then(static function ($value) use ($onFulfilledOrRejected) {
8787
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
@@ -129,6 +129,24 @@ public function cancel(): void
129129
}
130130
}
131131

132+
/**
133+
* @deprecated 3.0.0 Use `catch()` instead
134+
* @see self::catch()
135+
*/
136+
public function otherwise(callable $onRejected): PromiseInterface
137+
{
138+
return $this->catch($onRejected);
139+
}
140+
141+
/**
142+
* @deprecated 3.0.0 Use `finally()` instead
143+
* @see self::finally()
144+
*/
145+
public function always(callable $onFulfilledOrRejected): PromiseInterface
146+
{
147+
return $this->finally($onFulfilledOrRejected);
148+
}
149+
132150
private function resolver(callable $onFulfilled = null, callable $onRejected = null): callable
133151
{
134152
return function ($resolve, $reject) use ($onFulfilled, $onRejected) {

src/PromiseInterface.php

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function done(callable $onFulfilled = null, callable $onRejected = null):
6363
* @param callable $onRejected
6464
* @return PromiseInterface
6565
*/
66-
public function otherwise(callable $onRejected): PromiseInterface;
66+
public function catch(callable $onRejected): PromiseInterface;
6767

6868
/**
6969
* Allows you to execute "cleanup" type tasks in a promise chain.
@@ -82,8 +82,8 @@ public function otherwise(callable $onRejected): PromiseInterface;
8282
* rejected promise, `$newPromise` will reject with the thrown exception or
8383
* rejected promise's reason.
8484
*
85-
* `always()` behaves similarly to the synchronous finally statement. When combined
86-
* with `otherwise()`, `always()` allows you to write code that is similar to the familiar
85+
* `finally()` behaves similarly to the synchronous finally statement. When combined
86+
* with `catch()`, `finally()` allows you to write code that is similar to the familiar
8787
* synchronous catch/finally pair.
8888
*
8989
* Consider the following synchronous code:
@@ -103,14 +103,14 @@ public function otherwise(callable $onRejected): PromiseInterface;
103103
*
104104
* ```php
105105
* return doSomething()
106-
* ->otherwise('handleError')
107-
* ->always('cleanup');
106+
* ->catch('handleError')
107+
* ->finally('cleanup');
108108
* ```
109109
*
110110
* @param callable $onFulfilledOrRejected
111111
* @return PromiseInterface
112112
*/
113-
public function always(callable $onFulfilledOrRejected): PromiseInterface;
113+
public function finally(callable $onFulfilledOrRejected): PromiseInterface;
114114

115115
/**
116116
* The `cancel()` method notifies the creator of the promise that there is no
@@ -122,4 +122,38 @@ public function always(callable $onFulfilledOrRejected): PromiseInterface;
122122
* @return void
123123
*/
124124
public function cancel(): void;
125+
126+
/**
127+
* [Deprecated] Registers a rejection handler for a promise.
128+
*
129+
* This method continues to exist only for BC reasons and to ease upgrading
130+
* between versions. It is an alias for:
131+
*
132+
* ```php
133+
* $promise->catch($onRejected);
134+
* ```
135+
*
136+
* @param callable $onRejected
137+
* @return PromiseInterface
138+
* @deprecated 3.0.0 Use catch() instead
139+
* @see self::catch()
140+
*/
141+
public function otherwise(callable $onRejected): PromiseInterface;
142+
143+
/**
144+
* [Deprecated] Allows you to execute "cleanup" type tasks in a promise chain.
145+
*
146+
* This method continues to exist only for BC reasons and to ease upgrading
147+
* between versions. It is an alias for:
148+
*
149+
* ```php
150+
* $promise->finally($onFulfilledOrRejected);
151+
* ```
152+
*
153+
* @param callable $onFulfilledOrRejected
154+
* @return PromiseInterface
155+
* @deprecated 3.0.0 Use finally() instead
156+
* @see self::finally()
157+
*/
158+
public function always(callable $onFulfilledOrRejected): PromiseInterface;
125159
}

tests/PromiseTest.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,31 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro
224224
}
225225

226226
/** @test */
227+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithCatchFollowers()
228+
{
229+
gc_collect_cycles();
230+
$promise = new Promise(function () { });
231+
$promise->catch(function () { });
232+
unset($promise);
233+
234+
$this->assertSame(0, gc_collect_cycles());
235+
}
236+
237+
/** @test */
238+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithFinallyFollowers()
239+
{
240+
gc_collect_cycles();
241+
$promise = new Promise(function () { });
242+
$promise->finally(function () { });
243+
unset($promise);
244+
245+
$this->assertSame(0, gc_collect_cycles());
246+
}
247+
248+
/**
249+
* @test
250+
* @deprecated
251+
*/
227252
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers()
228253
{
229254
gc_collect_cycles();
@@ -234,7 +259,10 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro
234259
$this->assertSame(0, gc_collect_cycles());
235260
}
236261

237-
/** @test */
262+
/**
263+
* @test
264+
* @deprecated
265+
*/
238266
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers()
239267
{
240268
gc_collect_cycles();

0 commit comments

Comments
 (0)