krypt0nn / asynclib
PHP 7.4+中创建异步任务的功能库
Requires
- php: >=7.4
README
Asynclib是一个允许您在PHP 7.4+中创建异步任务的库
安装
composer require krypt0nn/asynclib
关于异步编程
* 黄色的任务是以异步方式运行的
此图显示了同步程序和异步程序之间的区别。前者在主进程中执行每个任务,因此如果您有一个从网站获取大文件的任务,则程序将在该任务完成之前暂停(滞后)。这也意味着您的程序中的其他任务将在此任务之后执行
异步程序并行执行任务。在Asynclib中,每个新任务都在另一个进程中运行,这意味着它们不会影响主程序并停止其执行。我们可以异步运行长时间高权重任务,并从主进程监控它们的状态,这将为我们提供一个宝贵的性能提升
基本用法
对于实际示例,您可以查看test目录
此外,请注意,此库仅适用于桌面使用。我尚未在网站上对其进行测试,也不知道它是否在那里工作或不起作用
每个任务都应该写在其自己的文件中。此文件应返回TaskRunner
对象。例如
<?php require 'vendor/autoload.php'; use Asynclib\TaskRunner; return new TaskRunner (function (array $options, TaskRunner $task) { // your task code goes here });
TaskRunner
构造函数内部的可调用参数接受2个参数:array $options
和TaskRunner $task
。前者是您在Task->run
方法中提供给此任务的参数数组,而后者是当前的TaskRunner
对象
要在您的主代码中运行此任务,您应使用Task
类
<?php require 'vendor/autoload.php'; use Asynclib\Task; // Create new task from file // and run it $task = Task::create ('path/to/task/file.php')->run ([ // here you can write some options // that will be available in TaskRunner // also you can run this method // without any arguments ]);
之后,TaskRunner
将在另一个进程中开始工作,因此它不会影响您当前进程中的代码,停止它或类似的事情
现在存储在我们$task
变量中的Task
对象具有许多有用的方法。但最重要的是update
方法。此方法将同步任务状态和处理事件
/** * Task state * null - task is not initialized * false - task is still running * true - task is done and you can get its output */ $state = $task->update ();
我们可以使用另一个主要方法wait
等待任务完成
// PHP 8 syntax $task->wait (milliseconds: 5000);
此方法有3个参数:?int $milliseconds = null
、int $delay = 100
和callable $callback = null
。第一个是在此函数停止工作后的毫秒数。如果您在此处写入null值,则此方法将等待任务完成。第二个参数定义了任务状态更新的延迟(update
方法调用)。最后一个参数是可调用参数,它接受当前的Task
对象,并在每次任务更新后运行。如果此可调用参数返回true
(布尔值)-则将停止等待方法
$task->wait (delay: 1000, callable: function () { echo 'Task is not finished yet' . PHP_EOL; });
Task
对象还有另一个有用的部分,您可以向它们提供事件。例如
$task->on ('some_event', function ($data, Task $task) { echo 'Hey! I got a message from task: '. $data . PHP_EOL; });
然后从TaskRunner
可调用中执行此事件
<?php require 'vendor/autoload.php'; use Asynclib\TaskRunner; return new TaskRunner (function (array $options, TaskRunner $task) { for ($i = 0; $i < 5; ++$i) { // Performing event "some_event" // in main process $task->perform ('some_event', 'Now I am at position '. ($i + 1)); sleep (1); } });
当调用update
方法时,将执行事件some_event
$data
参数可以是PHP可以序列化的任何内容,包括函数serialize
:字符串、数字、布尔值、数组、对象...
任务还有一个特殊的事件,当它完成时将调用该事件
$task->onFinished (function ($output, Task $task) { echo 'Hey! Task with id '. $task->id() . ' seems to be finished with output: '. $output . PHP_EOL; });
与Task
类似,TaskRunner
也有相同语法的相同事件。要从Task
(主进程)接收事件并执行它们,请使用TaskRunner->update
方法
要强制中断任务执行,您可以调用stop方法
$task->stop ();
它还将任务状态设置为0(刚刚初始化)
其他可用方法
任务池
您可以将一些任务合并到一个池中并一起运行
<?php require 'vendor/autoload.php'; use Asynclib\Pool; // Create tasks pool $pool = Pool::create ([ 'path/to_some_task.php', 'path/to_some_another_task.php', Task::create ('or_the_task/itself.php')->onFinished (function ($output) { echo 'Task finished with output: '. $output . PHP_EOL; }) ]); // Run pool execution $pool->run (); // Wait untill all tasks in this pool will be finished $pool->updateWhileExist ();
方法update
将更新池中所有任务的状态,并移除已经完成的任务。它还可以接受一个回调,该回调将用于每个未完成的任务。updateWhileExist
与Task
中的wait
类似,但工作方式与update
相同:接受一个可调用的函数,并为每个未完成的任务运行它,直到没有未完成的任务为止
您可以使用output
方法获取任务输出
$task_output = $pool->output ('task_id');
如果提供的任务ID不存在或任务尚未完成,则此方法将抛出异常
如果您不想处理异常,还可以使用outputOrNull
方法。如果任务未完成或不存在,则返回null值
方法add
可以向池中添加新任务
$pool->add (Task::create ('path_to_task.php'));
已知问题和待办事项
- 该库在技术上支持IPC协议,但尚未正常工作