摘要:生成器委托簡(jiǎn)單地翻譯官方文檔的描述中,通過生成器委托,可以將其他生成器可迭代的對(duì)象數(shù)組委托給外層生成器。外層的生成器會(huì)先順序委托出來的值,然后繼續(xù)本身中定義的值。文章介紹了的迭代生成器,協(xié)程,并實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的非阻塞服務(wù)器。
生成器委托
簡(jiǎn)單地翻譯官方文檔的描述:
PHP7中,通過生成器委托(yield from),可以將其他生成器、可迭代的對(duì)象、數(shù)組委托給外層生成器。外層的生成器會(huì)先順序 yield 委托出來的值,然后繼續(xù) yield 本身中定義的值。
利用 yield from 可以方便我們編寫比較清晰生成器嵌套,而代碼嵌套調(diào)用是編寫復(fù)雜系統(tǒng)所必需的。
上例子:
以上將輸出:
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自然,內(nèi)部生成器也可以接受它的父生成器發(fā)送的信息或者異常,因?yàn)?yield from 為父子生成器建立一個(gè)雙向的通道。不多說,上例子:
send($num); } $gen->send(null); foreach (range(1,5) as $num) { $gen->send($num); } //$gen->send("hello world"); //try it ,gay輸出和上個(gè)例子是一樣的。
生成器返回值如果生成器被迭代完成,或者運(yùn)行到 return 關(guān)鍵字,是會(huì)給這個(gè)生成器返回值的。
可以有兩種方法獲取這個(gè)返回值:使用 $ret = Generator::getReturn() 方法。
使用 $ret = yield from Generator() 表達(dá)式。
上例子:
getReturn(); } foreach (task() as $item) { ; }輸出結(jié)果就不貼了,想必大家都猜到。
可以看到 yield from 和 return 結(jié)合使得 yield 的寫法更像平時(shí)我們寫的同步模式的代碼了,畢竟,這就是 PHP 出生成器特性的原因之一呀。
一個(gè)非阻塞的web服務(wù)器時(shí)間回到2015年,鳥哥博客上轉(zhuǎn)載的一篇《 在PHP中使用協(xié)程實(shí)現(xiàn)多任務(wù)調(diào)度》。文章介紹了PHP5 的迭代生成器,協(xié)程,并實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的非阻塞 web 服務(wù)器。(鏈接見文末引用)
現(xiàn)在我們利用 PHP7 中的這兩個(gè)新特性重寫這個(gè) web 服務(wù)器,只需要 100 多行代碼。
代碼如下:
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... "; $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 = <<參考資料 [1] http://www.php.net/manual/zh/...
[2] http://www.laruence.com/2015/...
[3] http://blog.csdn.net/u0101613...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/25582.html
摘要:以下分別備忘版本的部分新增特性。而且,在生成器沒有輸出完全時(shí),使用會(huì)報(bào)錯(cuò)。報(bào)錯(cuò)定義常量數(shù)組多聲明數(shù)組解構(gòu)運(yùn)行時(shí)將部分指令轉(zhuǎn)為機(jī)器碼。對(duì)于計(jì)算密集型應(yīng)用有較高的性能提升。 以下分別備忘 PHP 7.0 & 7.1 版本的部分新增特性。 PHP 7.0 ?? 運(yùn)算符 $foo = null; $bar = $foo ?? 123; // 相當(dāng)于 $bar = isset($bar) ? ...
python中的生成器、迭代器、裝飾器分別是什么意思呢?具體的含義,一些其具體的用途,下面小編就給大家詳細(xì)的解答下。 一、裝飾器 由于一個(gè)函數(shù)能實(shí)現(xiàn)一種功能,現(xiàn)在想要在不改變其代碼的情況下,讓這個(gè)函數(shù)進(jìn)化一下,即能保持原來的功能,還能有新的"技能",怎么辦? 現(xiàn)已經(jīng)存在一個(gè)自定義的函數(shù)func1 deffunc1(): print('hello,worl...
摘要:最近項(xiàng)目中用的比較多,所以特地去了解,模仿一下實(shí)現(xiàn)先來看看使用的方法通過是通過使用生成器配合方法模擬的一個(gè)同步操作,這個(gè)技術(shù)有效的避免了傳統(tǒng)回調(diào)和形成的回調(diào)地獄。 最近項(xiàng)目中 asyn & await 用的比較多,所以特地去了解,模仿一下實(shí)現(xiàn)~ 先來看看 使用 async & await 的方法 async function d () { try { const a = a...
閱讀 2036·2021-11-08 13:14
閱讀 2944·2021-10-18 13:34
閱讀 2032·2021-09-23 11:21
閱讀 3595·2019-08-30 15:54
閱讀 1763·2019-08-30 15:54
閱讀 2933·2019-08-29 15:33
閱讀 2588·2019-08-29 14:01
閱讀 1949·2019-08-29 13:52