Skip to content

Commit

Permalink
Merge pull request #31 from reactphp/1.1-compat
Browse files Browse the repository at this point in the history
1.1 release for 2.0 compatibility
  • Loading branch information
jsor committed Jul 1, 2015
2 parents d6de8ca + 31a4b62 commit 444aa92
Show file tree
Hide file tree
Showing 13 changed files with 502 additions and 153 deletions.
13 changes: 10 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@ php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm

before_script:
- composer install
before_install:
- composer self-update

script: phpunit --coverage-text
install:
- composer install --prefer-source

script:
- phpunit -v --coverage-text
170 changes: 170 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ Table of Contents
* [Deferred](#deferred-1)
* [Promise](#promise-1)
* [Resolver](#resolver-1)
* [Functions](#functions)
* [resolve()](#resolve)
* [reject()](#reject)
* [all()](#all)
* [race()](#race)
* [any()](#any)
* [some()](#some)
* [map()](#map)
* [reduce()](#reduce)
* [When](#when)
* [When::all()](#whenall)
* [When::any()](#whenany)
Expand Down Expand Up @@ -109,6 +118,38 @@ The Promise represents the eventual outcome, which is either fulfillment
reason. The Promise provides mechanisms for arranging to call a function on its
value or reason, and produces a new Promise for the result.

Creates a promise whose state is controlled by the functions passed to
`$resolver`.

```php
$resolver = function (callable $resolve, callable $reject, callable $notify) {
// Do some work, possibly asynchronously, and then
// resolve or reject. You can notify of progress events
// along the way if you want/need.

$resolve($awesomeResult);
// or $resolve($anotherPromise);
// or $reject($nastyError);
// or $notify($progressNotification);
};

$promise = new React\Promise\Promise($resolver);
```

The promise constructor receives a resolver function which will be called
immediately with 3 arguments:

* `$resolve($value)` - Primary function that seals the fate of the
returned promise. Accepts either a non-promise value, or another promise.
When called with a non-promise value, fulfills promise with that value.
When called with another promise, e.g. `$resolve($otherPromise)`, promise's
fate will be equivalent to that of `$otherPromise`.
* `$reject($reason)` - Function that rejects the promise.
* `$notify($update)` - Function that issues progress events for the promise.

If the resolver throws an exception, the promise will be rejected with that
thrown exception as the rejection reason.

A Promise has a single method `then()` which registers new fulfilled, error and
progress handlers with this Promise (all parameters are optional):

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

### Functions

Useful functions for creating, joining, mapping and reducing collections of
promises.

#### resolve()

```php
$promise = React\Promise\resolve(mixed $promiseOrValue);
```

Creates a promise for the supplied `$promiseOrValue`.

If `$promiseOrValue` is a value, it will be the resolution value of the
returned promise.

If `$promiseOrValue` is a promise, it will simply be returned.

Note: The promise returned is always a promise implementing
[ExtendedPromiseInterface](#extendedpromiseinterface). If you pass in a custom
promise which only implements [PromiseInterface](#promiseinterface), this
promise will be assimilated to a extended promise following `$promiseOrValue`.

#### reject()

```php
$promise = React\Promise\reject(mixed $promiseOrValue);
```

Creates a rejected promise for the supplied `$promiseOrValue`.

If `$promiseOrValue` is a value, it will be the rejection value of the
returned promise.

If `$promiseOrValue` is a promise, its completion value will be the rejected
value of the returned promise.

This can be useful in situations where you need to reject a promise without
throwing an exception. For example, it allows you to propagate a rejection with
the value of another promise.

#### all()

```php
$promise = React\Promise\all(array|React\Promise\PromiseInterface $promisesOrValues);
```

Returns a promise that will resolve only once all the items in
`$promisesOrValues` have resolved. The resolution value of the returned promise
will be an array containing the resolution values of each of the items in
`$promisesOrValues`.

#### race()

```php
$promise = React\Promise\race(array|React\Promise\PromiseInterface $promisesOrValues);
```

Initiates a competitive race that allows one winner. Returns a promise which is
resolved in the same way the first settled promise resolves.

#### any()

```php
$promise = React\Promise\any(array|React\Promise\PromiseInterface $promisesOrValues);
```

Returns a promise that will resolve when any one of the items in
`$promisesOrValues` resolves. The resolution value of the returned promise
will be the resolution value of the triggering item.

The returned promise will only reject if *all* items in `$promisesOrValues` are
rejected. The rejection value will be an array of all rejection reasons.

#### some()

```php
$promise = React\Promise\some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany);
```

Returns a promise that will resolve when `$howMany` of the supplied items in
`$promisesOrValues` resolve. The resolution value of the returned promise
will be an array of length `$howMany` containing the resolution values of the
triggering items.

The returned promise will reject if it becomes impossible for `$howMany` items
to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items
reject). The rejection value will be an array of
`(count($promisesOrValues) - $howMany) + 1` rejection reasons.

#### map()

```php
$promise = React\Promise\map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc);
```

Traditional map function, similar to `array_map()`, but allows input to contain
promises and/or values, and `$mapFunc` may return either a value or a promise.

The map function receives each item as argument, where item is a fully resolved
value of a promise or value in `$promisesOrValues`.

#### reduce()

```php
$promise = React\Promise\reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null);
```

Traditional reduce function, similar to `array_reduce()`, but input may contain
promises and/or values, and `$reduceFunc` may return either a value or a
promise, *and* `$initialValue` may be a promise or a value for the starting
value.

### When

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

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

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

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

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

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

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

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

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

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

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

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

If `$promiseOrValue` is a value, it will be the rejection value of the
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
"description": "A lightweight implementation of CommonJS Promises/A for PHP",
"license": "MIT",
"authors": [
{"name": "Jan Sorgalla", "email": "jsorgalla@googlemail.com"}
{"name": "Jan Sorgalla", "email": "jsorgalla@gmail.com"}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-0": {
"React\\Promise": "src/"
}
},
"files": ["src/React/Promise/functions_include.php"]
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
"dev-master": "1.1-dev"
}
}
}
6 changes: 3 additions & 3 deletions src/React/Promise/Deferred.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
public function resolve($result = null)
{
if (null !== $this->completed) {
return Util::promiseFor($result);
return resolve($result);
}

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

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

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

public function reject($reason = null)
{
return $this->resolve(Util::rejectedPromiseFor($reason));
return $this->resolve(reject($reason));
}

public function progress($update = null)
Expand Down
2 changes: 1 addition & 1 deletion src/React/Promise/FulfilledPromise.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
trigger_error('Invalid $fulfilledHandler argument passed to then(), must be null or callable.', E_USER_NOTICE);
}

return Util::promiseFor($result);
return resolve($result);
} catch (\Exception $exception) {
return new RejectedPromise($exception);
}
Expand Down
2 changes: 1 addition & 1 deletion src/React/Promise/LazyPromise.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
{
if (null === $this->promise) {
try {
$this->promise = Util::promiseFor(call_user_func($this->factory));
$this->promise = resolve(call_user_func($this->factory));
} catch (\Exception $exception) {
$this->promise = new RejectedPromise($exception);
}
Expand Down
50 changes: 50 additions & 0 deletions src/React/Promise/Promise.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace React\Promise;

class Promise implements PromiseInterface
{
private $deferred;

public function __construct($resolver)
{
if (!is_callable($resolver)) {
throw new \InvalidArgumentException(
sprintf(
'The resolver argument must be of type callable, %s given.',
gettype($resolver)
)
);
}

$this->deferred = new Deferred();
$this->call($resolver);
}

public function then($fulfilledHandler = null, $errorHandler = null, $progressHandler = null)
{
return $this->deferred->then($fulfilledHandler, $errorHandler, $progressHandler);
}

private function call($callback)
{
$deferred = $this->deferred;

try {
call_user_func(
$callback,
function ($result = null) use ($deferred) {
$deferred->resolve($result);
},
function ($reason = null) use ($deferred) {
$deferred->reject($reason);
},
function ($update = null) use ($deferred) {
$deferred->progress($update);
}
);
} catch (\Exception $e) {
$this->deferred->reject($e);
}
}
}
2 changes: 1 addition & 1 deletion src/React/Promise/RejectedPromise.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function then($fulfilledHandler = null, $errorHandler = null, $progressHa
return new RejectedPromise($this->reason);
}

return Util::promiseFor(call_user_func($errorHandler, $this->reason));
return resolve(call_user_func($errorHandler, $this->reason));
} catch (\Exception $exception) {
return new RejectedPromise($exception);
}
Expand Down

0 comments on commit 444aa92

Please sign in to comment.