当前位置: 首页 > 后端技术 > PHP

PHP7中生成器的新特性yield-from&&return-values

时间:2023-03-29 19:04:30 PHP

generatordelegation简单翻译下官方文档的描述:在PHP7中,通过generatordelegation(yieldfrom),其他生成器和可迭代对象都可以,数组委托给外部构建器。外层生成器会先yield委托的值,然后继续yield自己定义的值。使用yieldfrom可以让我们更容易写出清晰的生成器嵌套,而代码嵌套调用是写复杂系统所必需的。上面的例子:send($num);}$gen->send(null);foreach(range(1,5)as$num){$gen->send($num);}//$gen->send("helloworld");//试一下,gay输出和前面的例子是一样的。生成器返回值如果生成器迭代完成,或者运行到return关键字,就会返回一个值给生成器。有两种方法可以获得这个返回值:使用$ret=Generator::getReturn()方法。使用$ret=yieldfromGenerator()表达式。上面的例子:getReturn();}foreach(task()as$item){;}输出结果就不贴出来了,大家一定猜到了。可以看到yieldfrom和return的结合使得yield的写法更像我们平时写的同步模式的代码。毕竟,这是PHP具有生成器功能的原因之一。一个非阻塞的web服务器早在2015年,鸟哥的博客就转载了一篇文章《 在PHP中使用协程实现多任务调度》。文章介绍了PHP5的迭代生成器、协程,并实现了一个简单的非阻塞web服务器。(链接见文末参考)现在我们利用PHP7中的这两个新特性来重写这个web服务器,只需要100多行代码。代码如下:socket=$socket;$this->masterCoSocket=$master??$这个;}publicfunctionaccept(){$isSelect=yieldfrom$this->onRead();$接受=空;如果($isSelect&&$as=stream_socket_accept($this->socket,0)){$acceptS=newCoSocket($as,$this);}返回$acceptS;}publicfunctionread($size){yieldfrom$this->onRead();yield($data=fread($this->socket,$size));返回$数据;}publicfunctionwrite($string){yieldfrom$this->onWriter();yieldfwrite($this->socket,$string);}publicfunctionclose(){unset($this->masterCoSocket->streamPoolRead[(int)$this->socket]);取消设置($this->masterCoSocket->streamPoolWrite[(int)$this->socket]);产量($success=@fclose($this->socket));返回$成功;}publicfunctiononRead($timeout=null){$this->masterCoSocket->streamPoolRead[(int)$this->socket]=$this->socket;$pool=$this->masterCoSocket->streamPoolRead;$rSocks=[];$wSocks=$eSocks=null;foreach($poolas$item){$rSocks[]=$item;}yield($num=stream_select($rSocks,$wSocks,$eSocks,$timeout));返回$num;}publicfunctiononWriter($timeout=null){$this->masterCoSocket->streamPoolWrite[(int)$this->socket]=$this->socket;$pool=$this->masterCoSocket->streamPoolRead;$wSocks=[];$rSocks=$eSocks=null;foreach($poolas$item){$wSocks[]=$item;}yield($num=stream_select($rSocks,$wSocks,$eSocks,$timeout));返回$num;}publicfunctiononRequest(){/**@varself$socket*/$socket=yieldfrom$this->accept();如果(空($socket)){返回假;}$data=yieldfrom$socket->read(8192);$response=call_user_func($this->handleCallback,$data);从$socket->write($response)产生;从$socket->close()返回收益;}publicstaticfunctionstart($port,callable$callback){echo"Startingserveratport$port...\n";$socket=@stream_socket_server("tcp://0.0.0.0:$port",$errNo,$errStr);如果(!$socket)抛出新异常($errStr,$errNo);stream_set_blocking($socket,0);$coSocket=newself($socket);$coSocket->handleCallback=$callback;函数gen($coSocket){/**@varself$coSocket*/while(true)yieldfrom$coSocket->onRequest();}foreach(gen($coSocket)作为$item){};}}CoSocket::start(8000,function($data){$response=<<