clue / promise-timeout
Requires
- php: >=5.3
- react/event-loop: ^1.2
- react/promise: ^3.2 || ^2.7.0 || ^1.2.1
Requires (Dev)
- phpunit/phpunit: ^9.6 || ^5.7 || ^4.8.36
README
基于 ReactPHP 的 Promise 超时实现的简单版本。
目录
使用方法
这个轻量级的库仅包含几个简单的函数。所有函数都位于 React\Promise\Timer
命名空间下。
以下示例使用完整的函数名,例如
React\Promise\Timer\timeout(…);
从 PHP 5.6+ 开始,您也可以将每个所需函数导入到您的代码中,如下所示
use function React\Promise\Timer\timeout; timeout(…);
或者,您也可以使用类似下面的导入语句
use React\Promise\Timer; Timer\timeout(…);
timeout()
timeout(PromiseInterface<T> $promise, float $time, ?LoopInterface $loop = null): PromiseInterface<T>
函数可用于取消耗时过长的操作。
您需要传入一个表示挂起操作的输入 $promise
和超时参数。它返回一个新的 Promise,具有以下解析行为
-
如果输入
$promise
在$time
秒内解析,则使用其满足值解析结果 Promise。 -
如果输入
$promise
在$time
秒内拒绝,则使用其拒绝值拒绝结果 Promise。 -
如果输入
$promise
在$time
秒内未解决,则 取消 操作并使用TimeoutException
拒绝结果 Promise。
内部,给定的 $time
值将用于启动一个定时器,该定时器在触发后将 取消 挂起操作。这意味着如果您传入一个非常小(或负数)的值,它仍然会启动定时器,因此将在未来最早可能的时间触发。
如果输入 $promise
已经解决,则结果 Promise 将立即解析或拒绝,而无需启动定时器。
此函数接受一个可选的 LoopInterface|null $loop
参数,可用于传入要使用的事件循环实例。您可以使用 null
值以使用 默认循环。除非您确定想要显式使用给定的事件循环实例,否则不应提供此值。
仅处理已解决值的常见用例如下所示
$promise = accessSomeRemoteResource(); React\Promise\Timer\timeout($promise, 10.0)->then(function ($value) { // the operation finished within 10.0 seconds });
更完整的示例可能如下所示
$promise = accessSomeRemoteResource(); React\Promise\Timer\timeout($promise, 10.0)->then( function ($value) { // the operation finished within 10.0 seconds }, function ($error) { if ($error instanceof React\Promise\Timer\TimeoutException) { // the operation has failed due to a timeout } else { // the input operation has failed due to some other error } } );
或者如果您正在使用 react/promise v3
React\Promise\Timer\timeout($promise, 10.0)->then(function ($value) { // the operation finished within 10.0 seconds })->catch(function (React\Promise\Timer\TimeoutException $error) { // the operation has failed due to a timeout })->catch(function (Throwable $error) { // the input operation has failed due to some other error });
如上所述,timeout()
函数将处理底层操作,如果它耗时过长。在这种情况下,您可以确保结果 Promise 总是以 TimeoutException
拒绝。除此之外,该函数将尝试 取消 底层操作。取消逻辑的责任留给了底层操作。
-
常见用例包括清理任何资源,如打开的网络套接字、文件句柄、终止外部进程或定时器。
-
如果给定的输入
$promise
不支持取消操作,则这是一个无操作(NO-OP)。这意味着虽然最终的结果将是拒绝的,但底层的输入$promise
可能仍然是挂起的,因此可以继续消耗资源。
此外,返回的承诺被实现为可以在挂起时取消。取消挂起的承诺将取消底层操作。如上所述,取消逻辑的责任留给了底层操作。
$promise = accessSomeRemoteResource(); $timeout = React\Promise\Timer\timeout($promise, 10.0); $timeout->cancel();
有关承诺取消的更多详细信息,请参阅承诺文档。
如果您想等待多个承诺解析,可以使用以下正常的承诺原语:
$promises = array( accessSomeRemoteResource(), accessSomeRemoteResource(), accessSomeRemoteResource() ); $promise = React\Promise\all($promises); React\Promise\Timer\timeout($promise, 10)->then(function ($values) { // *all* promises resolved });
这适用于所有承诺集合原语,例如all()
、race()
、any()
、some()
等。
有关承诺原语的更多详细信息,请参阅承诺文档。
sleep()
函数sleep(float $time, ?LoopInterface $loop = null): PromiseInterface<void>
可以用来创建一个在$time
秒后解决的新的承诺。
React\Promise\Timer\sleep(1.5)->then(function () { echo 'Thanks for waiting!' . PHP_EOL; });
内部,给定的$time
值将用于启动一个计时器,一旦触发,就会解决承诺。这意味着如果您传递一个非常小(或负数)的值,它仍然会启动一个计时器,因此将在未来最早可能的时间触发。
此函数接受一个可选的 LoopInterface|null $loop
参数,可用于传入要使用的事件循环实例。您可以使用 null
值以使用 默认循环。除非您确定想要显式使用给定的事件循环实例,否则不应提供此值。
返回的承诺被实现为可以在挂起时取消。取消挂起的承诺将使用RuntimeException
拒绝其值,并清理任何挂起的计时器。
$timer = React\Promise\Timer\sleep(2.0); $timer->cancel();
resolve()
自v1.8.0以来已弃用,请改用
sleep()
。
函数resolve(float $time, ?LoopInterface $loop = null): PromiseInterface<float>
可以用来创建一个在$time
秒后解决,并以$time
作为满足值的新的承诺。
React\Promise\Timer\resolve(1.5)->then(function ($time) { echo 'Thanks for waiting ' . $time . ' seconds' . PHP_EOL; });
内部,给定的$time
值将用于启动一个计时器,一旦触发,就会解决承诺。这意味着如果您传递一个非常小(或负数)的值,它仍然会启动一个计时器,因此将在未来最早可能的时间触发。
此函数接受一个可选的 LoopInterface|null $loop
参数,可用于传入要使用的事件循环实例。您可以使用 null
值以使用 默认循环。除非您确定想要显式使用给定的事件循环实例,否则不应提供此值。
返回的承诺被实现为可以在挂起时取消。取消挂起的承诺将使用RuntimeException
拒绝其值,并清理任何挂起的计时器。
$timer = React\Promise\Timer\resolve(2.0); $timer->cancel();
reject()
自v1.8.0以来已弃用,请改用
sleep()
。
函数reject(float $time, ?LoopInterface $loop = null): PromiseInterface<never>
可以用来创建一个新的承诺,它在$time
秒后拒绝,并带有TimeoutException
。
React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) { echo 'Rejected after ' . $e->getTimeout() . ' seconds ' . PHP_EOL; });
内部,给定的$time
值将用于启动一个计时器,一旦触发,就会拒绝承诺。这意味着如果您传递一个非常小(或负数)的值,它仍然会启动一个计时器,因此将在未来最早可能的时间触发。
此函数接受一个可选的 LoopInterface|null $loop
参数,可用于传入要使用的事件循环实例。您可以使用 null
值以使用 默认循环。除非您确定想要显式使用给定的事件循环实例,否则不应提供此值。
返回的承诺被实现为可以在挂起时取消。取消挂起的承诺将使用RuntimeException
拒绝其值,并清理任何挂起的计时器。
$timer = React\Promise\Timer\reject(2.0); $timer->cancel();
TimeoutException
TimeoutException
扩展了PHP的内置RuntimeException
。
getTimeout()
方法getTimeout(): float
可以用来获取以秒为单位的超时值。
安装
建议通过Composer安装此库。 您是Composer的新手吗?
此项目遵循SemVer。这将安装最新的支持版本。
composer require react/promise-timer:^1.11
有关版本升级的详细信息,请参阅变更日志。
此项目旨在在所有平台上运行,因此不需要任何PHP扩展,并支持在旧版PHP 5.3到当前PHP 8+和HHVM上运行。强烈建议使用此项目的最新支持版本。
测试
要运行测试套件,首先需要克隆此存储库,然后通过Composer安装所有依赖项。
composer install
要运行测试套件,请转到项目根目录并运行:
vendor/bin/phpunit
许可证
麻省理工学院,参见 许可证文件。