mirror of
https://github.com/danog/amp.git
synced 2024-12-11 17:09:40 +01:00
Add defer()
This commit is contained in:
parent
3dbebd2a77
commit
40aab8eef5
@ -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
29
test/DeferTest.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user