Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for react promises in combinators and coroutines #44

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
}
],
"require": {
"php": ">=5.5"
"php": ">=5.5",
"react/promise": "^2.4"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer suggest here, as it's not a requirement, but then we can't have any version constraints.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with the suggest

},
"require-dev": {
"phpunit/phpunit": "~4.8",
Expand Down
47 changes: 45 additions & 2 deletions lib/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;

/**
* Retrieve the application-wide event reactor instance
*
Expand Down Expand Up @@ -258,6 +260,9 @@ function all(array $promises) {
foreach ($promises as $key => $promise) {
if ($promise instanceof Promise) {
$promise->when($onResolve, [$struct, $key]);
} else if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
$promise->when($onResolve, [$struct, $key]);
} else {
$struct->results[$key] = $promise;
if (--$struct->remaining === 0) {
Expand Down Expand Up @@ -319,6 +324,9 @@ function some(array $promises) {
foreach ($promises as $key => $promise) {
if ($promise instanceof Promise) {
$promise->when($onResolve, [$struct, $key]);
} else if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
$promise->when($onResolve, [$struct, $key]);
} else {
$struct->results[$key] = $promise;
if (--$struct->remaining === 0) {
Expand Down Expand Up @@ -365,6 +373,9 @@ function any(array $promises) {
foreach ($promises as $key => $promise) {
if ($promise instanceof Promise) {
$promise->when($onResolve, [$struct, $key]);
} else if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
$promise->when($onResolve, [$struct, $key]);
} else {
$struct->results[$key] = $promise;
if (--$struct->remaining === 0) {
Expand Down Expand Up @@ -417,6 +428,9 @@ function first(array $promises) {
foreach ($promises as $key => $promise) {
if ($promise instanceof Promise) {
$promise->when($onResolve, [$struct, $key]);
} else if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
$promise->when($onResolve, [$struct, $key]);
} else {
$struct->remaining = 0;
$struct->promisor->succeed($promise);
Expand Down Expand Up @@ -479,6 +493,9 @@ function map(array $promises, callable $functor) {
foreach ($promises as $key => $promise) {
if ($promise instanceof Promise) {
$promise->when($onResolve, [$struct, $key]);
} else if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
$promise->when($onResolve, [$struct, $key]);
} else {
$struct->remaining--;
try {
Expand Down Expand Up @@ -565,6 +582,9 @@ function filter(array $promises, callable $functor = null) {
foreach ($promises as $key => $promise) {
if ($promise instanceof Promise) {
$promise->when($onResolve, [$struct, $key]);
} else if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
$promise->when($onResolve, [$struct, $key]);
} else {
$struct->remaining--;
try {
Expand Down Expand Up @@ -602,7 +622,9 @@ function filter(array $promises, callable $functor = null) {
* @return \Amp\Promise
*/
function pipe($promise, callable $functor) {
if (!$promise instanceof Promise) {
if ($promise instanceof ReactPromise) {
$promise = __transformReactPromise($promise);
} else if (!$promise instanceof Promise) {
try {
return new Success(\call_user_func($functor, $promise));
} catch (\Throwable $e) {
Expand Down Expand Up @@ -650,6 +672,9 @@ function promises(array $values) {
continue;
} elseif ($value instanceof Promisor) {
$values[$key] = $value->promise();
} else if ($value instanceof ReactPromise) {
$value = __transformReactPromise($value);
$values[$key] = $value;
} else {
$values[$key] = new Success($value);
}
Expand Down Expand Up @@ -740,6 +765,8 @@ function coroutine(callable $func) {
return resolve($out);
} elseif ($out instanceof Promise) {
return $out;
} else if ($out instanceof ReactPromise) {
return __transformReactPromise($promise);
} else {
return new Success($out);
}
Expand Down Expand Up @@ -785,7 +812,11 @@ function __coroutineAdvance(CoroutineState $cs) {
$result = (PHP_MAJOR_VERSION >= 7) ? $cs->generator->getReturn() : null;
$cs->promisor->succeed($result);
}
} elseif ($yielded instanceof Promise) {
} elseif ($yielded instanceof Promise || $yielded instanceof ReactPromise) {
if ($yielded instanceof ReactPromise) {
$yielded = __transformReactPromise($yielded);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For speed, it's probably better to move it further down and just duplicate the if block content.

if ($cs->nestingLevel < 3) {
$cs->nestingLevel++;
$yielded->when('Amp\__coroutineSend', $cs);
Expand Down Expand Up @@ -884,6 +915,18 @@ function __coroutineSend($error, $result, CoroutineState $cs) {
}
}

function __transformReactPromise(ReactPromise $promise) {
$deferred = new Deferred;

$promise->then(function($value) use ($deferred) {
$deferred->succeed($value);
}, function($error) use ($deferred) {
$deferred->fail($error);
});

return $deferred->promise();
}

/**
* A general purpose function for creating error messages from generator yields
*
Expand Down