mirror of
https://github.com/danog/amp.git
synced 2024-11-26 20:15:00 +01:00
Accept React promises in rethrow, wait, timeout, pipe, and capture
Fixes #75.
This commit is contained in:
parent
8b7fb9ece3
commit
f187d4b31a
@ -91,9 +91,19 @@ function call(callable $functor, ...$args): Promise {
|
||||
/**
|
||||
* Registers a callback that will forward the failure reason to the Loop error handler if the promise fails.
|
||||
*
|
||||
* @param \Amp\Promise $promise
|
||||
* @param \Amp\Promise|\React\Promise\PromiseInterface $promise
|
||||
*
|
||||
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
|
||||
*/
|
||||
function rethrow(Promise $promise) {
|
||||
function rethrow($promise) {
|
||||
if (!$promise instanceof Promise) {
|
||||
if ($promise instanceof ReactPromise) {
|
||||
$promise = adapt($promise);
|
||||
} else {
|
||||
throw new \TypeError("Must provide an instance of %s or %s", Promise::class, ReactPromise::class);
|
||||
}
|
||||
}
|
||||
|
||||
$promise->when(function ($exception) {
|
||||
if ($exception) {
|
||||
throw $exception;
|
||||
@ -104,13 +114,22 @@ function rethrow(Promise $promise) {
|
||||
/**
|
||||
* Runs the event loop until the promise is resolved. Should not be called within a running event loop.
|
||||
*
|
||||
* @param \Amp\Promise $promise
|
||||
* @param \Amp\Promise|\React\Promise\PromiseInterface $promise
|
||||
*
|
||||
* @return mixed Promise success value.
|
||||
*
|
||||
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
|
||||
* @throws \Throwable Promise failure reason.
|
||||
*/
|
||||
function wait(Promise $promise) {
|
||||
function wait($promise) {
|
||||
if (!$promise instanceof Promise) {
|
||||
if ($promise instanceof ReactPromise) {
|
||||
$promise = adapt($promise);
|
||||
} else {
|
||||
throw new \TypeError("Must provide an instance of %s or %s", Promise::class, ReactPromise::class);
|
||||
}
|
||||
}
|
||||
|
||||
$resolved = false;
|
||||
Loop::run(function () use (&$resolved, &$value, &$exception, $promise) {
|
||||
$promise->when(function ($e, $v) use (&$resolved, &$value, &$exception) {
|
||||
@ -135,12 +154,22 @@ function wait(Promise $promise) {
|
||||
/**
|
||||
* Pipe the promised value through the specified functor once it resolves.
|
||||
*
|
||||
* @param \Amp\Promise $promise
|
||||
* @param \Amp\Promise|\React\Promise\PromiseInterface $promise
|
||||
* @param callable(mixed $value): mixed $functor
|
||||
*
|
||||
* @return \Amp\Promise
|
||||
*
|
||||
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
|
||||
*/
|
||||
function pipe(Promise $promise, callable $functor): Promise {
|
||||
function pipe($promise, callable $functor): Promise {
|
||||
if (!$promise instanceof Promise) {
|
||||
if ($promise instanceof ReactPromise) {
|
||||
$promise = adapt($promise);
|
||||
} else {
|
||||
throw new \TypeError("Must provide an instance of %s or %s", Promise::class, ReactPromise::class);
|
||||
}
|
||||
}
|
||||
|
||||
$deferred = new Deferred;
|
||||
|
||||
$promise->when(function ($exception, $value) use ($deferred, $functor) {
|
||||
@ -160,14 +189,24 @@ function pipe(Promise $promise, callable $functor): Promise {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Amp\Promise $promise
|
||||
* @param \Amp\Promise|\React\Promise\PromiseInterface $promise
|
||||
* @param string $className Exception class name to capture. Given callback will only be invoked if the failure reason
|
||||
* is an instance of the given exception class name.
|
||||
* @param callable(\Throwable $exception): mixed $functor
|
||||
*
|
||||
* @return \Amp\Promise
|
||||
*
|
||||
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
|
||||
*/
|
||||
function capture(Promise $promise, string $className, callable $functor): Promise {
|
||||
function capture($promise, string $className, callable $functor): Promise {
|
||||
if (!$promise instanceof Promise) {
|
||||
if ($promise instanceof ReactPromise) {
|
||||
$promise = adapt($promise);
|
||||
} else {
|
||||
throw new \TypeError("Must provide an instance of %s or %s", Promise::class, ReactPromise::class);
|
||||
}
|
||||
}
|
||||
|
||||
$deferred = new Deferred;
|
||||
|
||||
$promise->when(function ($exception, $value) use ($deferred, $className, $functor) {
|
||||
@ -197,12 +236,22 @@ function capture(Promise $promise, string $className, callable $functor): Promis
|
||||
* If the timeout expires before the promise is resolved, the returned promise fails with an instance of
|
||||
* \Amp\TimeoutException.
|
||||
*
|
||||
* @param \Amp\Promise $promise
|
||||
* @param \Amp\Promise|\React\Promise\PromiseInterface $promise
|
||||
* @param int $timeout Timeout in milliseconds.
|
||||
*
|
||||
* @return \Amp\Promise
|
||||
*
|
||||
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
|
||||
*/
|
||||
function timeout(Promise $promise, int $timeout): Promise {
|
||||
function timeout($promise, int $timeout): Promise {
|
||||
if (!$promise instanceof Promise) {
|
||||
if ($promise instanceof ReactPromise) {
|
||||
$promise = adapt($promise);
|
||||
} else {
|
||||
throw new \TypeError("Must provide an instance of %s or %s", Promise::class, ReactPromise::class);
|
||||
}
|
||||
}
|
||||
|
||||
$deferred = new Deferred;
|
||||
$resolved = false;
|
||||
|
||||
|
@ -6,6 +6,7 @@ use Amp;
|
||||
use Amp\Failure;
|
||||
use Amp\Success;
|
||||
use Amp\Promise;
|
||||
use function React\Promise\reject;
|
||||
|
||||
class CaptureTest extends \PHPUnit\Framework\TestCase {
|
||||
public function testSuccessfulPromise() {
|
||||
@ -110,4 +111,33 @@ class CaptureTest extends \PHPUnit\Framework\TestCase {
|
||||
$this->assertFalse($invoked);
|
||||
$this->assertSame($exception, $reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFailedPromise
|
||||
*/
|
||||
public function testReactPromise() {
|
||||
$invoked = false;
|
||||
$callback = function ($exception) use (&$invoked, &$reason) {
|
||||
$invoked = true;
|
||||
$reason = $exception;
|
||||
return -1;
|
||||
};
|
||||
|
||||
$exception = new \Exception;
|
||||
|
||||
$promise = reject($exception);
|
||||
|
||||
$promise = Amp\capture($promise, \Exception::class, $callback);
|
||||
$this->assertInstanceOf(Promise::class, $promise);
|
||||
|
||||
$callback = function ($exception, $value) use (&$result) {
|
||||
$result = $value;
|
||||
};
|
||||
|
||||
$promise->when($callback);
|
||||
|
||||
$this->assertTrue($invoked);
|
||||
$this->assertSame($exception, $reason);
|
||||
$this->assertSame(-1, $result);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use Amp;
|
||||
use Amp\Failure;
|
||||
use Amp\Success;
|
||||
use Amp\Promise;
|
||||
use function React\Promise\resolve;
|
||||
|
||||
class PipeTest extends \PHPUnit\Framework\TestCase {
|
||||
public function testSuccessfulPromise() {
|
||||
@ -81,4 +82,31 @@ class PipeTest extends \PHPUnit\Framework\TestCase {
|
||||
$this->assertTrue($invoked);
|
||||
$this->assertSame($exception, $reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testSuccessfulPromise
|
||||
*/
|
||||
public function testReactPromise() {
|
||||
$invoked = false;
|
||||
$callback = function ($value) use (&$invoked) {
|
||||
$invoked = true;
|
||||
return $value + 1;
|
||||
};
|
||||
|
||||
$value = 1;
|
||||
|
||||
$promise = resolve($value);
|
||||
|
||||
$promise = Amp\pipe($promise, $callback);
|
||||
$this->assertInstanceOf(Promise::class, $promise);
|
||||
|
||||
$callback = function ($exception, $value) use (&$result) {
|
||||
$result = $value;
|
||||
};
|
||||
|
||||
$promise->when($callback);
|
||||
|
||||
$this->assertTrue($invoked);
|
||||
$this->assertSame($value + 1, $result);
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,10 @@ use Amp;
|
||||
use Amp\Failure;
|
||||
use Amp\Loop;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use function React\Promise\reject;
|
||||
|
||||
class RethrowTest extends TestCase {
|
||||
public function testWaitOnPendingPromise() {
|
||||
public function testRethrow() {
|
||||
$exception = new \Exception;
|
||||
|
||||
try {
|
||||
@ -24,4 +25,24 @@ class RethrowTest extends TestCase {
|
||||
|
||||
$this->fail('Failed promise reason should be thrown from loop');
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testRethrow
|
||||
*/
|
||||
public function testReactPromise() {
|
||||
$exception = new \Exception;
|
||||
|
||||
try {
|
||||
Loop::run(function () use ($exception) {
|
||||
$promise = reject($exception);
|
||||
|
||||
Amp\rethrow($promise);
|
||||
});
|
||||
} catch (\Exception $reason) {
|
||||
$this->assertSame($exception, $reason);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail('Failed promise reason should be thrown from loop');
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use Amp\Loop;
|
||||
use Amp\Pause;
|
||||
use Amp\Success;
|
||||
use Amp\Promise;
|
||||
use function React\Promise\resolve;
|
||||
|
||||
class TimeoutTest extends \PHPUnit\Framework\TestCase {
|
||||
public function testSuccessfulPromise() {
|
||||
@ -89,4 +90,26 @@ class TimeoutTest extends \PHPUnit\Framework\TestCase {
|
||||
|
||||
$this->assertInstanceOf(Amp\TimeoutException::class, $reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testSuccessfulPromise
|
||||
*/
|
||||
public function testReactPromise() {
|
||||
Loop::run(function () {
|
||||
$value = 1;
|
||||
|
||||
$promise = resolve($value);
|
||||
|
||||
$promise = Amp\timeout($promise, 100);
|
||||
$this->assertInstanceOf(Promise::class, $promise);
|
||||
|
||||
$callback = function ($exception, $value) use (&$result) {
|
||||
$result = $value;
|
||||
};
|
||||
|
||||
$promise->when($callback);
|
||||
|
||||
$this->assertSame($value, $result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use Amp\Failure;
|
||||
use Amp\Pause;
|
||||
use Amp\Success;
|
||||
use Amp\Loop;
|
||||
use function React\Promise\resolve;
|
||||
|
||||
class WaitTest extends \PHPUnit\Framework\TestCase {
|
||||
public function testWaitOnSuccessfulPromise() {
|
||||
@ -59,4 +60,17 @@ class WaitTest extends \PHPUnit\Framework\TestCase {
|
||||
|
||||
$result = Amp\wait($promise->promise());
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testWaitOnSuccessfulPromise
|
||||
*/
|
||||
public function testReactPromise() {
|
||||
$value = 1;
|
||||
|
||||
$promise = resolve($value);
|
||||
|
||||
$result = Amp\wait($promise);
|
||||
|
||||
$this->assertSame($value, $result);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user