PHP下的异步尝试系列PHP下的异步尝试一:初识GeneratorsPHP下的异步尝试二:初识协程:PHP版Promise【PHP下异步尝试五:PHP版Promise的持续改进】Generator类#http://php.net/manual/zh/class.generator.phpGeneratorimplementsIterator{/*Methods*///获取迭代器的当前值publicmixedcurrent(void)//获取迭代器的当前值publicmixedgetReturn(void)//返回当前生成的密钥publicmixedkey(void)//生成器从上次继续执行yieldpublicvoidnext(void)//重置迭代器publicvoidrewind(void)//引入一个值给thegeneratorpublicmixedsend(mixed$value)//向生成器抛出异常publicmixedthrow(Throwable$exception)//检查迭代器是否关闭publicboolvalid(void)//迭代时执行的方法tor已序列化publicvoid__wakeup(void)}生成生成器尝试实例化类$gen=newGenerator();#我们发现不能直接手动实例化#outputPHPphp:8尝试函数方式functiongen($max){for($i=0;$i<$maX;$i++){yield$i;}}$gen=gen(5);#success#成功,我们只需要在普通的函数方法中yield就可以成为生成器了。看懂php的生成器其实每一种语言都有生成器,比如python,go等生成器迭代foreach代码会证明有效,getReturnfunctiongen($max){for($i=0;$i<$max;$i++){产量$i;}return$max;}$gen=gen(5);foreach($genas$val){var_dump($val);}//如果已经迭代完成,获取返回值//php7支持//valid判断当前迭代器是否被迭代//getReturn返回迭代器的返回值if(version_compare(PHP_VERSION,'7.0.0')>=0&&!$gen->valid()){var_dump($gen->getReturn());}withkeyvalue生成器迭代的返回值foreach迭代器可以有key和value,类似functiongen($max){for($i=0;$i<$max;$i++){产量$i=>$i+1;}return$max;}$gen=gen(5);//var_dump($gen->key());//var_dump($gen->current());foreach($genas$key=>$val){var_dump($key."=>".$val);}#outputstring(4)"0=>1"string(4)"1=>2"string(4)"2=>3"string(4)"3=>4"string(4)"4=>5"GeneratoriterationManualiteration这段代码会演示rewind,next,sendmethodfunctiongen($max){for($i=0;$i<$最大;$i++){//这里的(yield$i)在php7之后的版本可以省略$res=(yield$i);变量转储($res);}return$max;}$gen=gen(10);//不能被调用,隐式调用//如果迭代不能在开始后倒带(即在使用next或send之后)$gen->rewind();//打印当前生成器的值var_dump("1::".$gen->current());//output:string(4)"1::0"//执行下面2行代码,会返回错误//$gen->next();//$gen->rewind();//继续执行直到下一次yield$gen->next();var_dump("2::".$gen->current());//输出:字符串(4)"2::1"$gen->next();var_dump("3::".$gen->current());//output:string(4)"3::2"//发送一个空值相当于调用next(这个方法尝试从python中的迭代器来,成功)$gen->send(null);var_dump("4::".$gen->current());//output:string(4)"4::3"//发送值会继续执行$gen->send(100);var_dump("5::".$gen->current());//output:string(4)"5::4"//如果已经迭代完成,获取返回值//php7支持if(version_compare(PHP_VERSION,'7.0.0')>=0&&!$gen->valid()){var_dump($gen->getReturn());}#output:string(4)"1::0"NULLstring(4)"2::1"NULLstring(4)"3::2"NULL字符串g(4)"4::3"int(100)string(4)"5::4"#先忽略掉gen中var_dump输出的NULL或int(100)#每次nextcurrent可以得到当前产量值并尝试理解发送函数gen($max){for($i=0;$i<$max;$i++){$res=(yield$i);的输出变量转储($res);}返回$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());#输出:字符串(4)"1::0"int(222)string(4)"2::1"int(333)string(4)"3::2"int(444)string(4)"4::3"#sendandnext#next()=>current=yieldvalue#send(val)$rs=yieldexpressionexecution=val;//这样发送理解就好了#在当前一个yield发送,在当前yield表达式返回,如果没有变量接收,那么在下一个yield继续返回$rs=(yieldsomethind_to_do(...));^|-----------------||屈服值||----------------------------||yieldexpressionyieldexpressionresult#执行顺序流程类似$res=(yield1);//<-var_dump("1::".$gen->current());第一步收益回报var_dump($res);//<-$gen->发送(222);第二步send:222之后继续往下$res=222然后var_dump($res),然后yield2$res=(yield2);//<-var_dump("2::".$gen->current());打印当前值2var_dump($res);//<-$gen->发送(333);第三步发送:333之后继续往下走$res=333然后var_dump($res),然后到达yield3$res=(yield3);//<-var_dump("3::".$gen->current());var_dump($res);//<-$gen->发送(null);第二步send:null之后,继续往下$res=null然后var_dump($res),然后到达yield4$res=(yield4);//<-var_dump("4::".$gen->current());生成器抛出错误#内部定义异常并返回,外部接收函数gen(){echo"Genbegins\n";yieldnewException('内部定义异常');echo"Genends\n";}$gen=gen();try{throw$gen->current();}catch(\Exception$e){echo"外部捕获异常:".$e->getMessage()。PHP_EOL;}$gen->send("123");#output:genstartsexternalcaughtexception:internaldefinedexceptiongenends#内部接收send传入的异常,然后直接抛出,外部接收函数gen(){echo"发电开始\n";throw(yieldnewException('内部定义异常'));echo"生成结束\n";}$gen=gen();try{throw$gen->current();}catch(\Exception$e){echo"Externalcaughtexception:".$e->getMessage()。PHP_EOL;}try{$gen->send(new\Exception("外部定义异常"));}catch(\Exception$e){echo"外部捕获异常:".$e->getMessage()。PHP_EOL;}#outputGenstart外部捕获异常:内部定义异常外部捕获异常:外部定义异常#functiongen(){echo"Genstarts\n";try{yieldnewException('内部定义异常');}catch(Exception$e){echo"InternalcaptureException:".“异常:{$e->getMessage()}\n”;}echo"EndofGen\n";}$gen=gen();try{throw$gen->current();}catch(\Exception$e){echo"外部捕获异常:".$e->getMessage()。PHP_EOL;}//注意这里是throw方法,相当于//$gen->send(new\Exception("ExternalDefineexception"));//throwyield(yieldreceive=new\Exception("外部定义异常"))$gen->throw(new\Exception("外部定义异常"));#outputgenstartexternalcaptureexception:Internallydefinedexceptions内部捕获异常:Exception:ExternaldefinedexceptionGen通信,改变执行体流程的顺序。后面我们会介绍使用场景和Co自动执行体等文章。重命名记录2018.09。HP下的生成器】->【PHP下的异步尝试1:初识生成器】
