站長資訊網
        最全最豐富的資訊網站

        帶你了解PHP7里生成器的新特性

        生成器委托

        簡單地翻譯官方文檔的描述:

        PHP7中,通過生成器委托(yield from),可以將其他生成器、可迭代的對象、數組委托給外層生成器。外層的生成器會先順序 yield 委托出來的值,然后繼續 yield 本身中定義的值。

        利用 yield from 可以方便我們編寫比較清晰生成器嵌套,而代碼嵌套調用是編寫復雜系統所必需的。

        上例子:

        <?php function 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 1 foo iteration 2 foo iteration 3 foo iteration 4 foo iteration 5 foo iteration 6 foo iteration 7 foo iteration 8 foo iteration 9 foo iteration 10 --- bar iteration 1 bar iteration 2 bar iteration 3 bar iteration 4 bar iteration 5

        自然,內部生成器也可以接受它的父生成器發送的信息或者異常,因為 yield from 為父子生成器建立一個雙向的通道。不多說,上例子:

        <?php function 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() 表達式。

        上例子:

        <?php function 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服務器

        時間回到2015年,鳥哥博客上轉載的一篇《 在PHP中使用協程實現多任務調度》。文章介紹了PHP5 的迭代生成器,協程,并實現了一個簡單的非阻塞 web 服務器。(鏈接見文末引用)

        現在我們利用 PHP7 中的這兩個新特性重寫這個 web 服務器,只需要 100 多行代碼。

        代碼如下:

        <?php  class 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 = <<<RES HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: close  hello world! RES;     return $response; });

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 久久精品国产精品亚洲艾草网美妙| 亚洲国模精品一区| 精品一区二区三区高清免费观看 | 国产精品久久毛片完整版| 亚洲精品国自产拍在线观看| 国产成人高清精品一区二区三区| 国产成人精品无码免费看| 亚洲AV日韩精品久久久久| 无码人妻精品一区二区蜜桃百度 | 无码日韩精品一区二区人妻| 国产精品色视频ⅹxxx | 伊人精品视频在线| 免费看一级毛片在线观看精品视频 | 国产精品自在线拍国产第一页| 69久久精品无码一区二区| 青草国产精品久久久久久| 亚洲精品色婷婷在线影院| 人妻少妇看A偷人无码精品| 精品无码综合一区| 黑巨人与欧美精品一区 | 99精品电影一区二区免费看| 日韩麻豆国产精品欧美| 久热这里只精品99re8久| 99re8这里有精品热视频免费| 亚洲动漫精品无码av天堂| 亚洲国产精品无码久久九九| 香港aa三级久久三级老师2021国产三级精品三级在 | 国产精品久久久久久久久久免费| 欧美日韩精品一区二区| 欧美精品一本久久男人的天堂| 国产精品欧美久久久天天影视| 2022国产精品不卡a| 99国产精品久久久久久久成人热| www.久久精品| 久久99热精品| 亚洲精品理论电影在线观看| 亚洲成人精品久久| 国产精品无码免费专区午夜| 精品国产热久久久福利| 日韩欧美一区二区三区中文精品 | 亚洲精品无码乱码成人 |