jaxwilko / weird-php
通过子进程实现异步PHP
Requires
- ext-pcntl: *
- laravel/serializable-closure: ^1.3
- react/event-loop: ^1.4.0
Requires (Dev)
- phpunit/phpunit: ^10
README
该项目旨在通过在多个进程中分配任务来为PHP添加异步支持。
要求
Weird需要
- PHP >= 8.2
- 访问
pcntl
方法(proc_open
、proc_get_status
、proc_terminate
)
安装
composer require jaxwilko/weird-php
使用
默认情况下,Weird与Promise
类一起工作,您也可以传递可调用参数,但您不会从它们那里收到输出。
use Weird\Promise; Promise::make(function (Thread $thread) { // do some really cool stuff $result = 'Hello world'; return $result; }) ->then(function (string $result) { echo $result; // Prints: Hello World }) ->catch(function (\Throwable $e) { // This will catch any exceptions happening parent process, not the child process. })
使用ProcessManager
,我们可以将多个进程分配到我们想要的任意数量的进程中。
use Weird\ProcessManager; use Weird\Processes\Thread; use Weird\Promise; $manager = ProcessManager::create() ->spawn(Thread::class, processes: 1); $manager->dispatch([ // Promise 1 Promise::make(function () { return 'hello'; })->then(fn ($str) => $str . ' world') ->then(fn ($str) => echo $str . PHP_EOL), // Promise 2 Promise::make(function () { return 'world'; })->then(fn ($str) => $str . ' hello') ->then(fn ($str) => echo $str . PHP_EOL) ]);
当创建一个新的进程时,它将失去对当前全局作用域的访问权限,这意味着诸如您的自动加载器之类的工具将不会加载。默认情况下,如果找到,Weird将尝试加载您的composer自动加载文件。或者,您可以通过
withBootstrap()
方法提供要注册自动加载器的文件。
$manager = ProcessManager::create() ->withBootstrap(__DIR__ . '/vendor/autoload.php') ->spawn(Thread::class);
由于这些进程是异步运行的,如果您想处理它们,您需要告诉进程管理器何时检查它们。要等待所有活动进程完成,请调用wait()
。等待还接受一个超时参数,该参数为秒的浮点数。
$manager = ProcessManager::create() ->spawn(Thread::class, processes: 1); $manager->dispatch(function () { // do something }); $manager->wait(timeout: 0.5);
或者,您可以手动调用tick()
函数,该函数将检查由子进程返回的承诺并进行处理。
$manager = ProcessManager::create() ->spawn(Thread::class, processes: 1); $manager->dispatch( Promise::make(function () { // do something })->then(function (string $output) { // do something else }) ); while ($doingSomethingElse) { // ... $manager->tick(); // ... }
提示
提示
是从一个进程发送的特殊消息,可以提供有关正在发生什么的反馈。
要发送一个提示
,您可以调用方法\Weird\Messages\Events\Hint::send($message)
。
可以在ProcessManager
对象上调用registerHintHandler()
来注册一个提示
处理程序。
$manager->registerHintHandler(function (mixed $message, Process $process) { echo $message; });
UnknownMessage
由于Weird如何监听输出流,通过直接向缓冲区输出发送的任何数据都将被捕获为UnknownMessage
。可以通过在ProcessManager
对象上调用registerUnknownMessageHandler()
来监听这些。
$manager->registerUnknownMessageHandler(function (mixed $message, Process $process) { echo $message; });
进程
在Weird中包含的Thread
进程允许您执行多个异步PHP操作。本文档的大部分内容概述了Thread
的使用,但是您可以实现自己的ParallelProcess
类,并用ProcessManager
来启动它。
例如
class MyCustomProcess extends \Weird\Processes\ParallelProcess { // Define how often tick should be executed in seconds protected float $tickRate = 1 / 32; public function register() { // execute startup tasks } public function read($stdin) { while ($message = $this->readStream($stdin)) { // do something with messages sent from the parent process } } public function tick() { // do something } } // ... $manager = ProcessManager::create() ->spawn(MyCustomProcess::class, processes: 5);