摘要:下的異步嘗試系列下的異步嘗試一初識(shí)生成器下的異步嘗試二初識(shí)協(xié)程下的異步嘗試三協(xié)程的版自動(dòng)執(zhí)行器下的異步嘗試四版的下的異步嘗試五版的的繼續(xù)完善生成器類獲取迭代器當(dāng)前值獲取迭代器當(dāng)前值返回當(dāng)前產(chǎn)生的鍵生成器從上一次處繼續(xù)執(zhí)行重置迭代器向生成器中
PHP下的異步嘗試系列
PHP下的異步嘗試一:初識(shí)生成器
PHP下的異步嘗試二:初識(shí)協(xié)程
PHP下的異步嘗試三:協(xié)程的PHP版thunkify自動(dòng)執(zhí)行器
PHP下的異步嘗試四:PHP版的Promise
[PHP下的異步嘗試五:PHP版的Promise的繼續(xù)完善]
生成器類# http://php.net/manual/zh/class.generator.php Generator implements Iterator { /* Methods */ //獲取迭代器當(dāng)前值 public mixed current ( void ) //獲取迭代器當(dāng)前值 public mixed getReturn ( void ) //返回當(dāng)前產(chǎn)生的鍵 public mixed key ( void ) //生成器從上一次yield處繼續(xù)執(zhí)行 public void next ( void ) //重置迭代器 public void rewind ( void ) //向生成器中傳入一個(gè)值 public mixed send ( mixed $value ) //向生成器中拋入一個(gè)異常 public mixed throw ( Throwable $exception ) //檢查迭代器是否被關(guān)閉 public bool valid ( void ) //迭代器序列化時(shí)執(zhí)行的方法 public void __wakeup ( void ) }生成生成器 嘗試實(shí)例化類
$gen = new Generator(); # 我們發(fā)現(xiàn)不能直接手動(dòng)實(shí)例化 # output PHP Fatal error: Uncaught Error: The "Generator" class is reserved for internal use and cannot be manually instantiated in /web/www/sxx_admin3/src/cache/test/amphp/gen3.php:8嘗試function方式
function gen($max) { for ($i=0; $i<$max; $i++) { yield $i; } } $gen = gen(5); # success # 成功,我們只需要在普通函數(shù)方法里yield即可成了生成器理解php的生成器
其實(shí)各語言都有生成器,比如python,go等
生成器迭代foreach被代碼將演示valid, getReturn
function gen($max) { for ($i=0; $i<$max; $i++) { yield $i; } return $max; } $gen = gen(5); foreach ($gen as $val) { var_dump($val); } //如果已經(jīng)迭代完成,獲取返回值 // php7 支持 // valid 判斷當(dāng)前迭代器是否迭代完成 // getReturn 返回迭代器的返回值 if (version_compare(PHP_VERSION, "7.0.0") >= 0 && !$gen->valid()) { var_dump($gen->getReturn()); }帶key值的生成器迭代foreach
迭代器返回值可以帶key和value,類似
function gen($max) { for ($i=0; $i<$max; $i++) { yield $i => $i+1; } return $max; } $gen = gen(5); //var_dump($gen->key()); //var_dump($gen->current()); foreach ($gen as $key=>$val) { var_dump($key . "=>" . $val); } # output string(4) "0=>1" string(4) "1=>2" string(4) "2=>3" string(4) "3=>4" string(4) "4=>5"生成器迭代手動(dòng)迭代
本代碼將演示rewind, next, send方法
function gen($max) { for ($i=0; $i<$max; $i++) { // 此處的(yield $i)在php7以后版本可省略 $res = (yield $i); var_dump($res); } return $max; } $gen = gen(10); // 可不調(diào)用,隱式調(diào)用 // 如果迭代開始后不能再rewind(即使用了next或send后) $gen->rewind(); // 打印獲取到當(dāng)前生成器的值 var_dump("1::" . $gen->current()); //output: string(4) "1::0" // 下面2句代碼執(zhí)行,將返回錯(cuò)誤 // $gen->next(); // $gen->rewind(); //繼續(xù)執(zhí)行,知道遇到下一個(gè)yield $gen->next(); var_dump("2::" . $gen->current()); //output: string(4) "2::1" $gen->next(); var_dump("3::" . $gen->current()); //output: string(4) "3::2" // send傳null值等同于調(diào)用next(本方法嘗試來自python的迭代器,成功) $gen->send(null); var_dump("4::" . $gen->current()); //output: string(4) "4::3" // send傳值會(huì)也會(huì)繼續(xù)執(zhí)行 $gen->send(100); var_dump("5::" . $gen->current()); //output: string(4) "5::4" //如果已經(jīng)迭代完成,獲取返回值 // php7 支持 if (version_compare(PHP_VERSION, "7.0.0") >= 0 && !$gen->valid()) { var_dump($gen->getReturn()); } # output: string(4) "1::0" NULL string(4) "2::1" NULL string(4) "3::2" NULL string(4) "4::3" int(100) string(4) "5::4" # 我們先不去理會(huì)gen里var_dump輸出的NULL或int(100) # 我們先去理解每次next后current可以獲取到當(dāng)前yield的值即可嘗試?yán)斫鈙end輸出
function gen($max) { for ($i=0; $i<$max; $i++) { $res = (yield $i); var_dump($res); } return $max; } $gen = gen(10); var_dump("1::" . $gen->current()); $gen->send(222); var_dump("2::" . $gen->current()); $gen->send(333); var_dump("3::" . $gen->current()); $gen->send(null); var_dump("4::" . $gen->current()); # output: string(4) "1::0" int(222) string(4) "2::1" int(333) string(4) "3::2" int(444) string(4) "4::3" # send和next # next() => current = yield值 # send(val) $rs = yield 表達(dá)式執(zhí)行 = val; //send這樣理解即可 # 在當(dāng)前某個(gè)yield處時(shí)send,當(dāng)前yield表達(dá)式處返回,如果沒有變量接收,那么繼續(xù)下一個(gè)yield處返回 $rs = (yield somethind_to_do(...) ); ^ |-------------------| | yield值 | |----------------------------| | yield 表達(dá)式 yield表達(dá)式結(jié)果 # 執(zhí)行順序流程類似 $res = (yield 1); // <- var_dump("1::" . $gen->current()); 第一步到y(tǒng)ield返回 var_dump($res); // <- $gen->send(222); 第二步send:222后,繼續(xù)往下走$res=222 然后var_dump($res), 然后到了yield 2 $res = (yield 2); // <- var_dump("2::" . $gen->current()); 打印當(dāng)前的值2 var_dump($res); // <- $gen->send(333); 第三步send:333后,繼續(xù)往下走$res=333 然后var_dump($res), 然后到了yield 3 $res = (yield 3); // <- var_dump("3::" . $gen->current()); var_dump($res); // <- $gen->send(null); 第二步send:null后,繼續(xù)往下走$res=null 然后var_dump($res), 然后到了yield 4 $res = (yield 4); // <- var_dump("4::" . $gen->current());生成器throw拋出錯(cuò)誤
# 內(nèi)部定義異常并返回,外部接收 function gen() { echo "Gen 開始 "; yield new Exception("內(nèi)部定義異常"); echo "Gen 結(jié)束 "; } $gen = gen(); try { throw $gen->current(); } catch (Exception $e) { echo "外部捕獲異常:" . $e->getMessage() . PHP_EOL; } $gen->send("123"); # output: Gen 開始 外部捕獲異常:內(nèi)部定義異常 Gen 結(jié)束 # 內(nèi)部接收send傳入的異常,然后直接throw,外部接收 function gen() { echo "Gen 開始 "; throw (yield new Exception("內(nèi)部定義異常")); echo "Gen 結(jié)束 "; } $gen = gen(); try { throw $gen->current(); } catch (Exception $e) { echo "外部捕獲異常:" . $e->getMessage() . PHP_EOL; } try { $gen->send(new Exception("外部定義異常")); } catch (Exception $e) { echo "外部捕獲異常:" . $e->getMessage() . PHP_EOL; } # output Gen 開始 外部捕獲異常:內(nèi)部定義異常 外部捕獲異常:外部定義異常 # function gen() { echo "Gen 開始 "; try { yield new Exception("內(nèi)部定義異常"); } catch (Exception $e) { echo "內(nèi)部捕獲異常:" . "Exception: {$e->getMessage()} "; } echo "Gen 結(jié)束 "; } $gen = gen(); try { throw $gen->current(); } catch (Exception $e) { echo "外部捕獲異常:" . $e->getMessage() . PHP_EOL; } // 注意這里是throw方法,相當(dāng)于 // $gen->send(new Exception("外部定義異常")); // throw yield (yield接收 = new Exception("外部定義異常")) $gen->throw(new Exception("外部定義異常")); #output Gen 開始 外部捕獲異常:內(nèi)部定義異常 內(nèi)部捕獲異常:Exception: 外部定義異常 Gen 結(jié)束總結(jié)
初識(shí)我們只需要先理解next和send即可 next->讓我們可以主動(dòng)自動(dòng)執(zhí)行迭代器 send->可以讓我們的迭代器實(shí)現(xiàn)雙向通信,改變執(zhí)行體流程順序 后續(xù)我們會(huì)介紹使用場景和Co自動(dòng)執(zhí)行體等文章更名記錄
2018.09.20: [PHP下的生成器嘗試一:初識(shí)PHP下的生成器] -> [PHP下的異步嘗試一:初識(shí)生成器]
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/30895.html
摘要:如果僅依靠程序自動(dòng)交出控制的話,那么一些惡意程序?qū)?huì)很容易占用全部時(shí)間而不與其他任務(wù)共享。多個(gè)操作可以在重疊的時(shí)間段內(nèi)進(jìn)行。 PHP下的異步嘗試系列 如果你還不太了解PHP下的生成器,你可以根據(jù)下面目錄翻閱 PHP下的異步嘗試一:初識(shí)生成器 PHP下的異步嘗試二:初識(shí)協(xié)程 PHP下的異步嘗試三:協(xié)程的PHP版thunkify自動(dòng)執(zhí)行器 PHP下的異步嘗試四:PHP版的Promise ...
摘要:結(jié)果打印我結(jié)論或問題這里我們基礎(chǔ)實(shí)現(xiàn)了一個(gè)可以用于生產(chǎn)環(huán)境的后續(xù)我們會(huì)接續(xù)完善這個(gè)的特有方法,比如等后續(xù)再介紹用實(shí)現(xiàn)的自動(dòng)執(zhí)行器等附錄參考中文對(duì)象入門阮一峰 PHP下的異步嘗試系列 如果你還不太了解PHP下的生成器和協(xié)程,你可以根據(jù)下面目錄翻閱 PHP下的異步嘗試一:初識(shí)生成器 PHP下的異步嘗試二:初識(shí)協(xié)程 PHP下的異步嘗試三:協(xié)程的PHP版thunkify自動(dòng)執(zhí)行器 PHP下的...
摘要:函數(shù)并不是生成器協(xié)程函數(shù)自動(dòng)執(zhí)行的唯一方案。因?yàn)樽詣?dòng)執(zhí)行的關(guān)鍵是,必須有一種機(jī)制,自動(dòng)控制生成器協(xié)程函數(shù)的流程,接收和交還程序的執(zhí)行權(quán)。回調(diào)函數(shù)可以做到這一點(diǎn),對(duì)象也可以做到這一點(diǎn)。本系列的下一篇,將介紹基于的實(shí)現(xiàn)的自動(dòng)執(zhí)行器。 PHP下的異步嘗試系列 如果你還不太了解PHP下的生成器和協(xié)程,你可以根據(jù)下面目錄翻閱 PHP下的異步嘗試一:初識(shí)生成器 PHP下的異步嘗試二:初識(shí)協(xié)程 P...
摘要:背景最近接到一個(gè)客戶需求,要求將學(xué)生的考試結(jié)果分析表格和圖表導(dǎo)出到。本著最好不要額外安裝軟件的原則,搜索過后分別嘗試了等等。但是實(shí)現(xiàn)效果都與預(yù)期差距較大。它們是開源命令行工具,使用渲染引擎將呈現(xiàn)為和各種圖像格式。它們不需要顯示或顯示服務(wù)。 背景 最近接到一個(gè)客戶需求,要求將學(xué)生的考試結(jié)果分析表格和圖表導(dǎo)出到PDF。表格使用的是普通的table,圖表引用了https://www.char...
摘要:背景最近接到一個(gè)客戶需求,要求將學(xué)生的考試結(jié)果分析表格和圖表導(dǎo)出到。本著最好不要額外安裝軟件的原則,搜索過后分別嘗試了等等。但是實(shí)現(xiàn)效果都與預(yù)期差距較大。它們是開源命令行工具,使用渲染引擎將呈現(xiàn)為和各種圖像格式。它們不需要顯示或顯示服務(wù)。 背景 最近接到一個(gè)客戶需求,要求將學(xué)生的考試結(jié)果分析表格和圖表導(dǎo)出到PDF。表格使用的是普通的table,圖表引用了https://www.char...
閱讀 1402·2021-11-22 09:34
閱讀 1378·2021-09-22 14:57
閱讀 3400·2021-09-10 10:50
閱讀 1371·2019-08-30 15:54
閱讀 3690·2019-08-29 17:02
閱讀 3472·2019-08-29 12:54
閱讀 2611·2019-08-27 10:57
閱讀 3316·2019-08-26 12:24