Swoole官方文档中对协程的示例大多按照一次请求一个协程(或脚本并发大量协程)的方式来举例说明,这种使用方式下提升的是整体的性能,而非单次请求的响应时间.
要提升单次请求的响应效率(或提升非网络服务下php脚本代码的运行效率),需要在业务代码中主动使用协程来处理那些可并发的,耗时的代码.
这时便涉及到协程数据交互的情况,官方文档中使用chan举了一个生产者消费者的例子,但是如果业务代码都按照这个风格的话较为复杂.
js及c#的async/await风格使用相对简单,所以结合Swoole协程的csp模型及php语法情况,仿照async/await的风格做了如下简单包装.
包装方法代码
class CoTask {
protected $chan = null;
public function __construct(\Chan $chan){
$this->chan = $chan;
}
public function wait(){
if($this->chan instanceof \Chan){
$result = $this->chan->pop();
$this->chan = null;
if(!empty($result['exception']) && $result['exception'] instanceof \Throwable){
throw $result['exception'];
}else{
return $result['result'];
}
}else{
throw new \Exception('exception');
}
}
}
function co_run($func){
$chan = new \Chan(1);
$task = new \CoTask($chan);
go(function() use ($chan,$func){
$result = ['result' => null,'exception' => null];
try{
$result['result'] = $func();
}catch (\Throwable $e){
$result['exception'] = $e;
}
$chan->push($result);
});
return $task;
}
function co_wait(&$task){
if($task instanceof \CoTask){
$task = $task->wait();
}
return $task;
}
调用举例
$test = co_run(function(){
//执行代码并返回结果
});
//执行其他代码
co_wait($test);//由于使用了chan的pop方法,所以需要当前在协程上下文
var_dump($test);
PHP7.4后箭头函数调用举例
$test = co_run(fn() => "单行的执行代码,如多行仍需按照原有方式");
//执行其他代码
co_wait($test);//由于使用了chan的pop方法,所以需要当前在协程上下文
var_dump($test);
总结
经过这样简单的包装,可以在业务代码中存在可并发的多次调用或循环调用场景下使用,压缩单次处理时间.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。