1
0
mirror of https://github.com/danog/amp.git synced 2024-12-11 17:09:40 +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); 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 * 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 * 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 * @deprecated No longer necessary with ext-fiber
*/ */
function call(callable $callback, ...$args): Promise function call(callable $callback, mixed ...$args): Promise
{ {
try { try {
$result = $callback(...$args); $result = $callback(...$args);
@ -190,7 +202,7 @@ namespace Amp
* *
* @deprecated No longer necessary with ext-fiber * @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)); Promise\rethrow(call($callback, ...$args));
} }
@ -203,6 +215,14 @@ namespace Amp
return new Delayed($milliseconds); 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. * Returns the current time relative to an arbitrary point in time.
* *
@ -212,14 +232,6 @@ namespace Amp
{ {
return Internal\getCurrentTime(); return Internal\getCurrentTime();
} }
/**
* Async sleep for the specified number of milliseconds.
*/
function sleep(int $milliseconds): void
{
await(delay($milliseconds));
}
} }
namespace Amp\Promise 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. * @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) { if (!$promise instanceof Promise) {
$promise = adapt($promise); $promise = adapt($promise);
@ -629,17 +641,15 @@ namespace Amp\Promise
* *
* @return Promise * @return Promise
*/ */
function wrap($promise, callable $callback): Promise function wrap(Promise|ReactPromise $promise, callable $callback): Promise
{ {
if ($promise instanceof ReactPromise) { if ($promise instanceof ReactPromise) {
$promise = adapt($promise); $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 { try {
$result = $callback($exception, $result); $result = $callback($exception, $result);
} catch (\Throwable $exception) { } 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);
}
}