Skip to content

Commit 444aa92

Browse files
committed
Merge pull request #31 from reactphp/1.1-compat
1.1 release for 2.0 compatibility
2 parents d6de8ca + 31a4b62 commit 444aa92

13 files changed

Lines changed: 502 additions & 153 deletions

.travis.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,15 @@ php:
55
- 5.3
66
- 5.4
77
- 5.5
8+
- 5.6
9+
- 7.0
10+
- hhvm
811

9-
before_script:
10-
- composer install
12+
before_install:
13+
- composer self-update
1114

12-
script: phpunit --coverage-text
15+
install:
16+
- composer install --prefer-source
17+
18+
script:
19+
- phpunit -v --coverage-text

README.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ Table of Contents
1818
* [Deferred](#deferred-1)
1919
* [Promise](#promise-1)
2020
* [Resolver](#resolver-1)
21+
* [Functions](#functions)
22+
* [resolve()](#resolve)
23+
* [reject()](#reject)
24+
* [all()](#all)
25+
* [race()](#race)
26+
* [any()](#any)
27+
* [some()](#some)
28+
* [map()](#map)
29+
* [reduce()](#reduce)
2130
* [When](#when)
2231
* [When::all()](#whenall)
2332
* [When::any()](#whenany)
@@ -109,6 +118,38 @@ The Promise represents the eventual outcome, which is either fulfillment
109118
reason. The Promise provides mechanisms for arranging to call a function on its
110119
value or reason, and produces a new Promise for the result.
111120

121+
Creates a promise whose state is controlled by the functions passed to
122+
`$resolver`.
123+
124+
```php
125+
$resolver = function (callable $resolve, callable $reject, callable $notify) {
126+
// Do some work, possibly asynchronously, and then
127+
// resolve or reject. You can notify of progress events
128+
// along the way if you want/need.
129+
130+
$resolve($awesomeResult);
131+
// or $resolve($anotherPromise);
132+
// or $reject($nastyError);
133+
// or $notify($progressNotification);
134+
};
135+
136+
$promise = new React\Promise\Promise($resolver);
137+
```
138+
139+
The promise constructor receives a resolver function which will be called
140+
immediately with 3 arguments:
141+
142+
* `$resolve($value)` - Primary function that seals the fate of the
143+
returned promise. Accepts either a non-promise value, or another promise.
144+
When called with a non-promise value, fulfills promise with that value.
145+
When called with another promise, e.g. `$resolve($otherPromise)`, promise's
146+
fate will be equivalent to that of `$otherPromise`.
147+
* `$reject($reason)` - Function that rejects the promise.
148+
* `$notify($update)` - Function that issues progress events for the promise.
149+
150+
If the resolver throws an exception, the promise will be rejected with that
151+
thrown exception as the rejection reason.
152+
112153
A Promise has a single method `then()` which registers new fulfilled, error and
113154
progress handlers with this Promise (all parameters are optional):
114155

@@ -184,17 +225,134 @@ is making progress toward its result.
184225
All consumers are notified by having their `$progressHandler` (which they
185226
registered via `$promise->then()`) called with `$update`.
186227

228+
### Functions
229+
230+
Useful functions for creating, joining, mapping and reducing collections of
231+
promises.
232+
233+
#### resolve()
234+
235+
```php
236+
$promise = React\Promise\resolve(mixed $promiseOrValue);
237+
```
238+
239+
Creates a promise for the supplied `$promiseOrValue`.
240+
241+
If `$promiseOrValue` is a value, it will be the resolution value of the
242+
returned promise.
243+
244+
If `$promiseOrValue` is a promise, it will simply be returned.
245+
246+
Note: The promise returned is always a promise implementing
247+
[ExtendedPromiseInterface](#extendedpromiseinterface). If you pass in a custom
248+
promise which only implements [PromiseInterface](#promiseinterface), this
249+
promise will be assimilated to a extended promise following `$promiseOrValue`.
250+
251+
#### reject()
252+
253+
```php
254+
$promise = React\Promise\reject(mixed $promiseOrValue);
255+
```
256+
257+
Creates a rejected promise for the supplied `$promiseOrValue`.
258+
259+
If `$promiseOrValue` is a value, it will be the rejection value of the
260+
returned promise.
261+
262+
If `$promiseOrValue` is a promise, its completion value will be the rejected
263+
value of the returned promise.
264+
265+
This can be useful in situations where you need to reject a promise without
266+
throwing an exception. For example, it allows you to propagate a rejection with
267+
the value of another promise.
268+
269+
#### all()
270+
271+
```php
272+
$promise = React\Promise\all(array|React\Promise\PromiseInterface $promisesOrValues);
273+
```
274+
275+
Returns a promise that will resolve only once all the items in
276+
`$promisesOrValues` have resolved. The resolution value of the returned promise
277+
will be an array containing the resolution values of each of the items in
278+
`$promisesOrValues`.
279+
280+
#### race()
281+
282+
```php
283+
$promise = React\Promise\race(array|React\Promise\PromiseInterface $promisesOrValues);
284+
```
285+
286+
Initiates a competitive race that allows one winner. Returns a promise which is
287+
resolved in the same way the first settled promise resolves.
288+
289+
#### any()
290+
291+
```php
292+
$promise = React\Promise\any(array|React\Promise\PromiseInterface $promisesOrValues);
293+
```
294+
295+
Returns a promise that will resolve when any one of the items in
296+
`$promisesOrValues` resolves. The resolution value of the returned promise
297+
will be the resolution value of the triggering item.
298+
299+
The returned promise will only reject if *all* items in `$promisesOrValues` are
300+
rejected. The rejection value will be an array of all rejection reasons.
301+
302+
#### some()
303+
304+
```php
305+
$promise = React\Promise\some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany);
306+
```
307+
308+
Returns a promise that will resolve when `$howMany` of the supplied items in
309+
`$promisesOrValues` resolve. The resolution value of the returned promise
310+
will be an array of length `$howMany` containing the resolution values of the
311+
triggering items.
312+
313+
The returned promise will reject if it becomes impossible for `$howMany` items
314+
to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
315+
reject). The rejection value will be an array of
316+
`(count($promisesOrValues) - $howMany) + 1` rejection reasons.
317+
318+
#### map()
319+
320+
```php
321+
$promise = React\Promise\map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc);
322+
```
323+
324+
Traditional map function, similar to `array_map()`, but allows input to contain
325+
promises and/or values, and `$mapFunc` may return either a value or a promise.
326+
327+
The map function receives each item as argument, where item is a fully resolved
328+
value of a promise or value in `$promisesOrValues`.
329+
330+
#### reduce()
331+
332+
```php
333+
$promise = React\Promise\reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null);
334+
```
335+
336+
Traditional reduce function, similar to `array_reduce()`, but input may contain
337+
promises and/or values, and `$reduceFunc` may return either a value or a
338+
promise, *and* `$initialValue` may be a promise or a value for the starting
339+
value.
340+
187341
### When
188342

189343
The `React\Promise\When` class provides useful methods for creating, joining,
190344
mapping and reducing collections of Promises.
191345

346+
> **Note:** Since version 1.1 `React\Promise\When` acts only as a proxy for the [Promise functions](#functions) and its usage is discouraged.
347+
192348
#### When::all()
193349

194350
``` php
195351
$promise = React\Promise\When::all(array|React\Promise\PromiseInterface $promisesOrValues, callable $fulfilledHandler = null, callable $errorHandler = null, callable $progressHandler = null);
196352
```
197353

354+
> **Note:** Since version 1.1, [`React\Promise\all()`](#all) is preferred over `React\Promise\When::all()`.
355+
198356
Returns a Promise that will resolve only once all the items in
199357
`$promisesOrValues` have resolved. The resolution value of the returned Promise
200358
will be an array containing the resolution values of each of the items in
@@ -206,6 +364,8 @@ will be an array containing the resolution values of each of the items in
206364
$promise = React\Promise\When::any(array|React\Promise\PromiseInterface $promisesOrValues, callable $fulfilledHandler = null, callable $errorHandler = null, callable $progressHandler = null);
207365
```
208366

367+
> **Note:** Since version 1.1, [`React\Promise\any()`](#any) is preferred over `React\Promise\When::any()`.
368+
209369
Returns a Promise that will resolve when any one of the items in
210370
`$promisesOrValues` resolves. The resolution value of the returned Promise
211371
will be the resolution value of the triggering item.
@@ -219,6 +379,8 @@ rejected. The rejection value will be an array of all rejection reasons.
219379
$promise = React\Promise\When::some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany, callable $fulfilledHandler = null, callable $errorHandler = null, callable $progressHandler = null);
220380
```
221381

382+
> **Note:** Since version 1.1, [`React\Promise\some()`](#some) is preferred over `React\Promise\When::some()`.
383+
222384
Returns a Promise that will resolve when `$howMany` of the supplied items in
223385
`$promisesOrValues` resolve. The resolution value of the returned Promise
224386
will be an array of length `$howMany` containing the resolution values of the
@@ -235,6 +397,8 @@ reject). The rejection value will be an array of
235397
$promise = React\Promise\When::map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc);
236398
```
237399

400+
> **Note:** Since version 1.1, [`React\Promise\map()`](#map) is preferred over `React\Promise\When::map()`.
401+
238402
Traditional map function, similar to `array_map()`, but allows input to contain
239403
Promises and/or values, and `$mapFunc` may return either a value or a Promise.
240404

@@ -247,6 +411,8 @@ value of a Promise or value in `$promisesOrValues`.
247411
$promise = React\Promise\When::reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null);
248412
```
249413

414+
> **Note:** Since version 1.1, [`React\Promise\reduce()`](#reduce) is preferred over `React\Promise\When::reduce()`.
415+
250416
Traditional reduce function, similar to `array_reduce()`, but input may contain
251417
Promises and/or values, and `$reduceFunc` may return either a value or a
252418
Promise, *and* `$initialValue` may be a Promise or a value for the starting
@@ -258,6 +424,8 @@ value.
258424
$promise = React\Promise\When::resolve(mixed $promiseOrValue);
259425
```
260426

427+
> **Note:** Since version 1.1, [`React\Promise\resolve()`](#resolve) is preferred over `React\Promise\When::resolve()`.
428+
261429
Creates a resolved Promise for the supplied `$promiseOrValue`.
262430

263431
If `$promiseOrValue` is a value, it will be the resolution value of the
@@ -271,6 +439,8 @@ If `$promiseOrValue` is a Promise, it will simply be returned.
271439
$promise = React\Promise\When::reject(mixed $promiseOrValue);
272440
```
273441

442+
> **Note:** Since version 1.1, [`React\Promise\reject()`](#reject) is preferred over `React\Promise\When::reject()`.
443+
274444
Creates a rejected Promise for the supplied `$promiseOrValue`.
275445

276446
If `$promiseOrValue` is a value, it will be the rejection value of the

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33
"description": "A lightweight implementation of CommonJS Promises/A for PHP",
44
"license": "MIT",
55
"authors": [
6-
{"name": "Jan Sorgalla", "email": "jsorgalla@googlemail.com"}
6+
{"name": "Jan Sorgalla", "email": "jsorgalla@gmail.com"}
77
],
88
"require": {
99
"php": ">=5.3.3"
1010
},
1111
"autoload": {
1212
"psr-0": {
1313
"React\\Promise": "src/"
14-
}
14+
},
15+
"files": ["src/React/Promise/functions_include.php"]
1516
},
1617
"extra": {
1718
"branch-alias": {
18-
"dev-master": "1.0-dev"
19+
"dev-master": "1.1-dev"
1920
}
2021
}
2122
}

src/React/Promise/Deferred.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
5252
public function resolve($result = null)
5353
{
5454
if (null !== $this->completed) {
55-
return Util::promiseFor($result);
55+
return resolve($result);
5656
}
5757

58-
$this->completed = Util::promiseFor($result);
58+
$this->completed = resolve($result);
5959

6060
$this->processQueue($this->handlers, $this->completed);
6161

@@ -66,7 +66,7 @@ public function resolve($result = null)
6666

6767
public function reject($reason = null)
6868
{
69-
return $this->resolve(Util::rejectedPromiseFor($reason));
69+
return $this->resolve(reject($reason));
7070
}
7171

7272
public function progress($update = null)

src/React/Promise/FulfilledPromise.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
2222
trigger_error('Invalid $fulfilledHandler argument passed to then(), must be null or callable.', E_USER_NOTICE);
2323
}
2424

25-
return Util::promiseFor($result);
25+
return resolve($result);
2626
} catch (\Exception $exception) {
2727
return new RejectedPromise($exception);
2828
}

src/React/Promise/LazyPromise.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
1616
{
1717
if (null === $this->promise) {
1818
try {
19-
$this->promise = Util::promiseFor(call_user_func($this->factory));
19+
$this->promise = resolve(call_user_func($this->factory));
2020
} catch (\Exception $exception) {
2121
$this->promise = new RejectedPromise($exception);
2222
}

src/React/Promise/Promise.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace React\Promise;
4+
5+
class Promise implements PromiseInterface
6+
{
7+
private $deferred;
8+
9+
public function __construct($resolver)
10+
{
11+
if (!is_callable($resolver)) {
12+
throw new \InvalidArgumentException(
13+
sprintf(
14+
'The resolver argument must be of type callable, %s given.',
15+
gettype($resolver)
16+
)
17+
);
18+
}
19+
20+
$this->deferred = new Deferred();
21+
$this->call($resolver);
22+
}
23+
24+
public function then($fulfilledHandler = null, $errorHandler = null, $progressHandler = null)
25+
{
26+
return $this->deferred->then($fulfilledHandler, $errorHandler, $progressHandler);
27+
}
28+
29+
private function call($callback)
30+
{
31+
$deferred = $this->deferred;
32+
33+
try {
34+
call_user_func(
35+
$callback,
36+
function ($result = null) use ($deferred) {
37+
$deferred->resolve($result);
38+
},
39+
function ($reason = null) use ($deferred) {
40+
$deferred->reject($reason);
41+
},
42+
function ($update = null) use ($deferred) {
43+
$deferred->progress($update);
44+
}
45+
);
46+
} catch (\Exception $e) {
47+
$this->deferred->reject($e);
48+
}
49+
}
50+
}

src/React/Promise/RejectedPromise.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
2222
return new RejectedPromise($this->reason);
2323
}
2424

25-
return Util::promiseFor(call_user_func($errorHandler, $this->reason));
25+
return resolve(call_user_func($errorHandler, $this->reason));
2626
} catch (\Exception $exception) {
2727
return new RejectedPromise($exception);
2828
}

0 commit comments

Comments
 (0)