1
0
mirror of https://github.com/danog/amp.git synced 2024-12-03 09:57:51 +01:00

Add defer()

This commit is contained in:
Aaron Piotrowski 2020-10-04 10:22:21 -05:00
parent 3dbebd2a77
commit 40aab8eef5
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
2 changed files with 55 additions and 16 deletions

View File

@ -75,6 +75,18 @@ namespace Amp
return static fn(mixed ...$args): Promise => async($callback, ...$args);
}
/**
* Executes the given callback in a new green thread using {@see async()}, forwarding any exceptions thrown to
* the event loop error handler using {@see Promise\rethrow()}.
*
* @param callable(mixed ...$args):void $callback
* @param mixed ...$args
*/
function defer(callable $callback, mixed ...$args): void
{
Promise\rethrow(async($callback, ...$args));
}
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
* Generators as coroutines. The returned function always returns a promise when invoked. Errors have to be handled
@ -156,7 +168,7 @@ namespace Amp
*
* @deprecated No longer necessary with ext-fiber
*/
function call(callable $callback, ...$args): Promise
function call(callable $callback, mixed ...$args): Promise
{
try {
$result = $callback(...$args);
@ -190,7 +202,7 @@ namespace Amp
*
* @deprecated No longer necessary with ext-fiber
*/
function asyncCall(callable $callback, ...$args): void
function asyncCall(callable $callback, mixed ...$args): void
{
Promise\rethrow(call($callback, ...$args));
}
@ -203,6 +215,14 @@ namespace Amp
return new Delayed($milliseconds);
}
/**
* Async sleep for the specified number of milliseconds.
*/
function sleep(int $milliseconds): void
{
await(delay($milliseconds));
}
/**
* Returns the current time relative to an arbitrary point in time.
*
@ -212,14 +232,6 @@ namespace Amp
{
return Internal\getCurrentTime();
}
/**
* Async sleep for the specified number of milliseconds.
*/
function sleep(int $milliseconds): void
{
await(delay($milliseconds));
}
}
namespace Amp\Promise
@ -249,7 +261,7 @@ namespace Amp\Promise
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*
*/
function rethrow(Promise|ReactPromise $promise)
function rethrow(Promise|ReactPromise $promise): void
{
if (!$promise instanceof Promise) {
$promise = adapt($promise);
@ -629,17 +641,15 @@ namespace Amp\Promise
*
* @return Promise
*/
function wrap($promise, callable $callback): Promise
function wrap(Promise|ReactPromise $promise, callable $callback): Promise
{
if ($promise instanceof ReactPromise) {
$promise = adapt($promise);
} elseif (!$promise instanceof Promise) {
throw createTypeError([Promise::class, ReactPromise::class], $promise);
}
$deferred = new Deferred();
$deferred = new Deferred;
$promise->onResolve(static function (\Throwable $exception = null, $result) use ($deferred, $callback) {
$promise->onResolve(static function (?\Throwable $exception, mixed $result) use ($deferred, $callback): void {
try {
$result = $callback($exception, $result);
} catch (\Throwable $exception) {

29
test/DeferTest.php Normal file
View File

@ -0,0 +1,29 @@
<?php
namespace Amp\Test;
use Amp\Loop;
use Amp\PHPUnit\AsyncTestCase;
use Amp\PHPUnit\TestException;
use function Amp\defer;
use function Amp\sleep;
class DeferTest extends AsyncTestCase
{
public function testExceptionsRethrownToLoopHandler(): void
{
Loop::setErrorHandler(function (\Throwable $exception) use (&$reason): void {
$reason = $exception;
});
$exception = new TestException;
defer(function () use ($exception): void {
throw $exception;
});
sleep(0); // Tick event loop.
$this->assertSame($exception, $reason);
}
}