sue/event-loop
提供基于reactphp的event-loop
Requires
- php: >=5.6.0
- react/event-loop: ^1.3
- react/promise: ^2.9
- react/promise-timer: ^1.10
Requires (Dev)
- phpunit/phpunit: ^9.3 || ^5.7
README
提供基于ReactPHP的全局唯一的EventLoop
什么是ReactPHP?
ReactPHP是一款基于PHP的事件驱动组件。核心是提供EventLoop,然后基于EventLoop提供各种组件,比如I/O处理,定时器等。
目录
loop
获取全局唯一的eventLoop对象
use Sue\EventLoop\loop; $loop = loop(); //loop启动后程序就会阻塞在这 //如果loop上没有任何待处理的callback, loop则自动退出 $loop->run(); //loop停止运行 $loop->stop();
isLoopRunning
判断全局的eventloop是否正在运行中
setInterval(1, function () { if (isLoopRunning()) { echo "Loop is running"; } }); loop()->run();
await
await($promise, $timeout)
启动一个临时eventloop来处理promise,当promise被settle后终止当前eventloop。该方法适用于传统的阻塞php模型(比如php-fpm)中使用异步的特性。方法返回promise resolved的值或者抛出异常 *** 该方法无法在一个已启动eventloop中使用 ***
try { $promise = someIoHeavyOperation(); $result = await($promise); //程序会阻塞在这里一直等待$promise被resolved或者rejected handle($result); } catch (Throwable $e) { //error handle }
//await方法第个参数接受一个float作为promise的timeout,以免promise长时间阻塞程序流程 $result = await($promise, 10);
setTimeout
setTimeout
方法可以在eventloop上添加一个一次性的timer
use Sue\EventLoop\setTimeout; use Sue\EventLoop\loop; use Sue\EventLoop\cancelTimer; //延迟5秒执行 setTimeout(5, function () { echo "hello world from 5 seconds ago"; }); loop()->run(); //提前终止执行 $timer = setTimeout(5, function () { echo "hello world from 5 seconds ago"; }); cancelTimer($timer); loop()->run();
setInterval
setInterval
方法可以在eventloop上添加一个可以重复执行的timer
use React\EventLoop\TimerInterface; use function Sue\EventLoop\setInterval; use function Sue\EventLoop\cancelTimer; //每60秒执行一次 setInterval(60, function () { echo "one minute has been passed\n"; }); // 中止运行 $timer = setInterval(1, function (string $name, int $age, TimerInterface $timer) { if ($some_condition) { cancelTimer($timer); } }, 'foo', 18); loop()->run();
cancelTimer
cancelTimer
可以取消一个已经注册的timer对象
use React\EventLoop\TimerInterface; use function Sue\EventLoop\setInterval; use function Sue\EventLoop\cancelTimer; $timer = setInterval(1, function (TimerInterface $timer) { echo "working...\n"; }); if ($some_condition) { cancelTimer($timer); }
nextTick
nextTick
可以在eventloop上注册一个在下一轮tick时执行的回调,对比setTimeout(0, $callback)
,nextTick($callback)
有更高优先级
use RuntimeException; use Sue\EventLoop\Exceptions\PromiseCancelledException; use function Sue\EventLoop\nextTick; $promise = nextTick(function () { return "hello world"; }); $promise->then(function (string $content) { //handler }); //异常处理 $promise = nextTick(function () { throw new RuntimeException('boom'); }); $promise->then(null, function (RuntimeException $e) { echo "error: " . $e; }); //中止执行 $promise = nextTick(function () { return "hello world"; }); if ($some_condition) { $promise->cancel(); } $promise->otherwise(function (PromiseCancelledException $exception) { //exception });
throttle
throttle
(节流)可以在eventloop上创建一个一次性的timer,但是会在N秒内同样的操作只会执行一次
use Sue\EventLoop\loop; use Sue\EventLoop\throttle; use Sue\EventLoop\setInterval; $callback = function () { echo "hello world\n"; }; setInterval(1, function () use ($callback) { static $count = 10; while ($count--) { echo "tick\n"; throttle(3, $callback); } }); loop()->run(); /** expect output tick tick tick hello world tick tick tick hello world tick tick tick hello world tick **/ //如果想提前手动中止 $promise = throttle(3, $callback); if ($some_condition) { $promise->cancel(); } $promise->otherwise(function (PromiseCancelledException $exception) { //exception });
throttleById
throttleById
方法同throttle
,除了需要自行设置唯一id值,throttle
是由callable的性质来计算唯一id
debounce
debounce
(防抖)可以在eventloop上注册一个一次性timer,但是在N秒内每次同样的操作都会延迟N秒后再执行
use Sue\EventLoop\loop; use Sue\EventLoop\debounce; use Sue\EventLoop\setInterval; $callback = function () { echo "hello world\n"; }; debounce(1, function () use ($callback) { static $count = 10; while ($count--) { echo "tick\n"; throttle(3, $callback); } }); loop()->run(); /** expect output tick tick tick tick tick tick tick tick tick tick hello world **/ //如果想提前中止 $promise = debounce(1, $callback); if ($some_condition) { $promise->cancel(); } $promise->otherwise(function (PromiseCancelledException $exception) { //exception });
debounceById
debounceById
方法同debounce
,除了需要自行设置唯一id值
install
$ composer require sue/event-loop
tests
克隆项目后执行
$ composer install $ ./vendor/bin/phpunit
许可证
MIT许可证 (MIT)
版权所有 (c) 2023 张东海
在此特此授予任何获得本软件及其相关文档副本(以下简称“软件”)的人士,免费、不可撤销的使用、复制、修改、合并、发布、分发、再许可和/或出售副本的权利,并允许软件的接受者进行上述操作,前提是
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
本软件按“现状”提供,不提供任何明示或暗示的保证,包括但不限于适销性、针对特定目的的适用性和非侵权性。在任何情况下,作者或版权所有者不对任何索赔、损害或其他责任(无论因合同、侵权或其他方式引起)承担责任,即使已收到有关软件或其使用的通知。