krypt0nn/asynclib

PHP 7.4+中创建异步任务的功能库

0.2.1 2021-08-19 16:44 UTC

This package is auto-updated.

Last update: 2024-09-19 23:26:49 UTC


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 $optionsTaskRunner $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 = nullint $delay = 100callable $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将更新池中所有任务的状态,并移除已经完成的任务。它还可以接受一个回调,该回调将用于每个未完成的任务。updateWhileExistTask中的wait类似,但工作方式与update相同:接受一个可调用的函数,并为每个未完成的任务运行它,直到没有未完成的任务为止

您可以使用output方法获取任务输出

$task_output = $pool->output ('task_id');

如果提供的任务ID不存在或任务尚未完成,则此方法将抛出异常

如果您不想处理异常,还可以使用outputOrNull方法。如果任务未完成或不存在,则返回null值

方法add可以向池中添加新任务

$pool->add (Task::create ('path_to_task.php'));

已知问题和待办事项

  • 该库在技术上支持IPC协议,但尚未正常工作

作者:Nikita Podvirnyy