fiasco / async
使用pcntl运行异步运行时PHP子进程的PHP库。
4.1-beta3
2023-10-12 00:58 UTC
Requires
- psr/log: ~2.0 || ~3.0
- react/socket: ^1.11.0
- seld/signal-handler: ^1.2
- symfony/event-dispatcher: ^6.0
Requires (Dev)
- phpunit/phpunit: ^9
- symfony/console: ^6.0
README
用于异步执行任务的PHP库。
此库允许您通过PCNTL扩展使用子进程并行执行匿名函数。
匿名函数的返回值将被序列化并返回给父进程以进行处理。
注意:不支持序列化对象作为返回值。
注意:由于异常对象可能包含无法序列化的对象,因此不建议将它们用作onSuccess回调函数的返回值。
如果您想运行异步活动,如文件操作或服务器交互,请考虑使用ReactPHP(此库依赖于ReactPHP)。
安装
推荐使用composer进行安装。
composer require fiasco/async:^3.0
使用方法
请参阅示例。
使用分叉管理器创建并行执行的分叉。
<?php use Async\ForkManager; use Async\ForkInterface; use Async\Exception\ChildExceptionDetected; $forkManager = new ForkManager(); // Return an instance of ForkInterface. // Will be either a SynchronousFork or an AsynchronousFork if PCNTL extension // is enabled. $fork = $forkManager->create(); // This anonymous function will run inside a child fork. $fork->run(function (ForkInterface $fork) { return file_get_contents('https://google.com/'); }); // Return contents from run function will be provided as the input argument // to the onSuccess callback. This anonymous function is run in the parent thread. $fork->onSuccess(function ($html) { echo "Got website with a length of ".strlen($html)." bytes\n"; }); // On error is called when the child process encounters an uncaught throwable. $fork->onError(function (ChildExceptionDetected $e) { echo "ERROR: ".$e->getMessage().PHP_EOL; }); // Block on main thread until all forks have completed. $forkManager->awaitForks();
您还可以将调用链在一起
<?php use Async\ForkManager; use Async\ForkInterface; use Async\Exception\ChildExceptionDetected; $forkManager = new ForkManager(); $forkManager->create() ->run(function (ForkInterface $fork) { return file_get_contents('https://google.com/'); }) ->onSuccess(function ($html) { echo "Got website with a length of ".strlen($html)." bytes\n"; }) ->onError(function (ChildExceptionDetected $e) { echo "ERROR: ".$e->getMessage().PHP_EOL; }); // Block on main thread until all forks have completed. $forkManager->awaitForks();
如果您喜欢在foreach循环中使用结果,可以使用ForkManager->getForkResults()
返回结果。要包含错误,请将true
作为函数的第一个参数传递。
<?php use Async\ForkManager; $forkManager = new ForkManager(); // Wait up to 3 seconds for fork response before giving up. $forkManager->setWaitTimeout(3); // This will result in a caught fatal error from the child. $forkManager->create()->run(fn() => @$foo->doNothing()); // This fork will catch a thrown exception and trigger the onError callback // in the parent thread. $forkManager->create()->run(function (ForkInterface $fork) { // You can set labels inside the fork to give better information about // what the specific fork is doing. $fork->setLabel("Fork that throws an error."); throw new \Exception('bar'); }); // Waiting for the fork in parent will timeout and force the fork // to error out. The Fork child will still attempt to return the // result but it will fail. $forkManager->create()->run(function (ForkInterface $fork) { $fork->setLabel("Fork that will timeout."); sleep(4); return 'fuz'; }); $forkManager->create()->run(fn() => 'baz'); $forkManager->awaitForks(); // Loop over errored forks. foreach ($forkManager->getForks(ForkInterface::STATUS_ERROR) as $fork) { // Result will be instance Async\Exception\ChildExceptionDetected. echo sprintf("Fork '%s' encountered an error:\n", $fork->getLabel()); // echo $fork->getResult()->getMessage() . PHP_EOL; } foreach ($forkManager->getForks(ForkInterface::STATUS_COMPLETE) as $fork) { // Result will be instance Async\Exception\ChildExceptionDetected. echo sprintf("Fork '%s' completed.\n", $fork->getLabel()); // echo $fork->getResult()->getMessage() . PHP_EOL; }
作为onError回调的替代方案,您还可以使用getForks()方法获取所有出错的分叉。
<?php use Async\ForkInterface; // .. create forks. // Wait for all forks to complete. $forkManager->awaitForks(); // Loop over errored forks. foreach ($forkManager->getForks(ForkInterface::STATUS_ERROR) as $fork) { // Result will be instance Async\Exception\ChildExceptionDetected. echo sprintf("Fork '%s' encountered an error:\n", $fork->getLabel()); echo $fork->getResult()->getMessage() . PHP_EOL; }