PHP7中生成器的新特性:生成器委托(yield-from)&返回值(return-value)

PHP7中生成器的新特性:生成器委托(yield-from)&返回值(return-value)

内容导读

收集整理的这篇技术教程文章主要介绍了PHP7中生成器的新特性:生成器委托(yield-from)&返回值(return-value),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4994字,纯文字阅读大概需要8分钟

内容图文

这篇文章给大家介绍的内容是关于PHP7中生成器的新特性:生成器委托( yield-from )&返回值(return-value),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

生成器委托

简单地翻译官方文档的描述:

PHP7中,通过生成器委托(yield from),可以将其他生成器、可迭代的对象、数组委托给外层生成器。外层的生成器会先顺序 yield 委托出来的值,然后继续 yield 本身中定义的值。

利用 yield from 可以方便我们编写比较清晰生成器嵌套,而代码嵌套调用是编写复杂系统所必需的。
上例子:

<?phpfunction echoTimes($msg, $max) {

for ($i = 1; $i <= $max; ++$i) {



echo "$msg iteration $in";



yield;

}} function task() {

yield from echoTimes('foo', 10); // print foo ten times

echo "---n";

yield from echoTimes('bar', 5); // print bar five times}foreach (task() as $item) {

;}

以上将输出:

foo iteration 1foo iteration 2foo iteration 3foo iteration 4foo iteration 5foo iteration 6foo iteration 7foo iteration 8foo iteration 9foo iteration 10---bar iteration 1bar iteration 2bar iteration 3bar iteration 4bar iteration 5

自然,内部生成器也可以接受它的父生成器发送的信息或者异常,因为 yield from 为父子生成器建立一个双向的通道。不多说,上例子:

<?phpfunction echoMsg($msg) {

while (true) {



$i = yield;



if($i === null){





break;



}



if(!is_numeric($i)){





throw new Exception("Hoo! must give me a number");



}



echo "$msg iteration $in";

}}function task2() {

yield from echoMsg('foo');

echo "---n";

yield from echoMsg('bar');}$gen = task2();foreach (range(1,10) as $num) {

$gen->send($num);}$gen->send(null);foreach (range(1,5) as $num) {

$gen->send($num);}//$gen->send("hello world"); //try it ,gay

输出和上个例子是一样的。

生成器返回值

如果生成器被迭代完成,或者运行到 return 关键字,是会给这个生成器返回值的。
可以有两种方法获取这个返回值:

  1. 使用 $ret = Generator::getReturn() 方法。

  2. 使用 $ret = yield from Generator() 表达式。

上例子:

<?phpfunction echoTimes($msg, $max) {

for ($i = 1; $i <= $max; ++$i) {



echo "$msg iteration $in";



yield;

}

return "$msg the end value : $in";}function task() {

$end = yield from echoTimes('foo', 10);

echo $end;

$gen = echoTimes('bar', 5);

yield from $gen;

echo $gen->getReturn();}foreach (task() as $item) {

;}

输出结果就不贴了,想必大家都猜到。

可以看到 yield from 和 return 结合使得 yield 的写法更像平时我们写的同步模式的代码了,毕竟,这就是 PHP 出生成器特性的原因之一呀。

一个非阻塞的web服务器

现在我们利用 PHP7 中的这两个新特性重写这个 web 服务器,只需要 100 多行代码。

代码如下:

<?phpclass CoSocket{

protected $masterCoSocket = null;

public $socket;

protected $handleCallback;

public $streamPoolRead = [];

public $streamPoolWrite = [];

public function __construct($socket, CoSocket $master = null)

{



$this->socket = $socket;



$this->masterCoSocket = $master ?? $this;

}

public function accept()

{



$isSelect = yield from $this->onRead();



$acceptS = null;



if ($isSelect && $as = stream_socket_accept($this->socket, 0)) {





$acceptS = new CoSocket($as, $this);



}



return $acceptS;

}

public function read($size)

{



yield from $this->onRead();



yield ($data = fread($this->socket, $size));



return $data;

}

public function write($string)

{



yield from $this->onWriter();



yield fwrite($this->socket, $string);

}

public function close()

{



unset($this->masterCoSocket->streamPoolRead[(int)$this->socket]);



unset($this->masterCoSocket->streamPoolWrite[(int)$this->socket]);



yield ($success = @fclose($this->socket));



return $success;

}

public function onRead($timeout = null)

{



$this->masterCoSocket->streamPoolRead[(int)$this->socket] = $this->socket;



$pool = $this->masterCoSocket->streamPoolRead;



$rSocks = [];



$wSocks = $eSocks = null;



foreach ($pool as $item) {





$rSocks[] = $item;



}



yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout));



return $num;

}

public function onWriter($timeout = null)

{



$this->masterCoSocket->streamPoolWrite[(int)$this->socket] = $this->socket;



$pool = $this->masterCoSocket->streamPoolRead;



$wSocks = [];



$rSocks = $eSocks = null;



foreach ($pool as $item) {





$wSocks[] = $item;



}



yield ($num = stream_select($rSocks, $wSocks, $eSocks, $timeout));



return $num;

}

public function onRequest()

{



/** @var self $socket */



$socket = yield from $this->accept();



if (empty($socket)) {





return false;



}



$data = yield from $socket->read(8192);



$response = call_user_func($this->handleCallback, $data);



yield from $socket->write($response);



return yield from $socket->close();

}

public static function start($port, callable $callback)

{



echo "Starting server at port $port...n";



$socket = @stream_socket_server("tcp://0.0.0.0:$port", $errNo, $errStr);



if (!$socket) throw new Exception($errStr, $errNo);



stream_set_blocking($socket, 0);



$coSocket = new self($socket);



$coSocket->handleCallback = $callback;



function gen($coSocket)



{





/** @var self $coSocket */





while (true) yield from $coSocket->onRequest();



}



foreach (gen($coSocket) as $item){};

}}CoSocket::start(8000, function ($data) {

$response = <<<RESHTTP/1.1 200 OKContent-Type: text/plainContent-Length: 12Connection: closehello world!RES;

return $response;});

相关文章推荐:

PHP生成器Generators的简单解析

以上就是PHP7中生成器的新特性:生成器委托( yield-from )&返回值(return-value)的详细内容,更多请关注Gxl网其它相关文章!

内容总结

以上是为您收集整理的PHP7中生成器的新特性:生成器委托(yield-from)&amp;返回值(return-value)全部内容,希望文章能够帮你解决PHP7中生成器的新特性:生成器委托(yield-from)&amp;返回值(return-value)所遇到的程序开发问题。 如果觉得技术教程内容还不错,欢迎将网站推荐给程序员好友。

内容备注

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。


本文关键词:

联系我们

在线咨询:点击这里给我发消息

邮件:w420220301@qq.com