react / promise-timer
基于 ReactPHP 的简单 Promise 超时实现。
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();
有关承诺取消的更多详细信息,请参阅Promise 文档。
如果您想等待多个承诺解析,您可以使用这样的正常承诺原语
$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()
等。
有关承诺原语的更多详细信息,请参阅Promise 文档。
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 上运行。强烈建议使用此项目的最新支持 PHP 版本。
测试
要运行测试套件,您首先需要克隆此存储库,然后通过Composer 安装所有依赖项
composer install
要运行测试套件,请转到项目根目录并运行
vendor/bin/phpunit
许可
MIT,请参阅许可证文件。