/首页
/开源
/关于
PHP中的yield与协程(二十节)
发表@2020-02-26 22:02:03
更新@2023-04-27 12:31:06
大家好,我是诚实且憨厚而又不失优雅的老李,我完美地太监了十二天。 我遇到一件比较逗逼的事情,我简单说说你们感受一下,自从我开公众号后文章的难度系数大概是从容易到逐渐变难,阅读量逐渐呈现降低的趋势。现在基本上都维持在每篇大概200阅读量左右,但是上周六我发了一篇关于回京的文章,1076的阅读量显得「鸡立鹤群」,场面也一度十分尴尬... ![](https://ti-node.com/static/upload/PNP/a/img_6.png#width-full) 这个数据让我开始怀疑人生,但在经过了一番痛定思痛以及思考后,我认为是我这篇文章蹭了肺炎的热点流量。很显然,我坚信大家还是一定非常热爱学习热爱读技术文章的: ![](https://ti-node.com/static/upload/PNP/a/img_7.png#width-full) 尽管阅读量一再新低,但是这《PHP网络编程》还是得坚持写下去一直到写完,主要是找不到接盘的英雄。我看了下目录,这本书我已经完成大概四分之三了,这周如果能再猛押一口恒河水,劲头一上来估计这周就能完成了。 众所周知(大概几十个人知道)老李之前是写过关于PHP的yield的,一共写了两篇而是算是上下篇关系,本来还打算写第三篇但是却像快刀斩乱麻般得太监了,并不是因为我懒,而是我发现如果要写好第三篇PHP的yield必须要铺垫一大堆关于IO的基础知识才行,现如今忽如一夜春风来、玉树流光照后庭,条件允许了一切都成熟饱满了,请让我开始复读PHP的yield。 Yield是PHP 5.5之后引入的新功能,其实隔壁家的Python也有这个玩意。有一天你的老板拿着一个内存只有100KB的智能硬件,这个硬件的功能就是不断从1循环到10000,你急不可耐、动手动脚,很快拍了拍油光锃亮的脑袋活生生憋出来了一段代码: ```php valid() ){ echo $generator->current().PHP_EOL; $generator->next(); } ``` ![](https://ti-node.com/static/upload/PNP/a/img_10.png#width-full) 这个yield_range()有点儿神了,TA似乎能记住变量$start数值当前状态,简单说就是第N次调用时候变量$start的值为X,而第N+1次调用的时候变量$start的值为X+1。 你是不是想到了类似于操作系统中进程上下文切换?进程A在某个时刻被CPU停止,然后调度进程B开始跑,然后停止进程B后重新开始跑进程A,那么进程A再次从「就绪态」轮换到「运行态」的时候,一切的一切都还要从上次停止的时候继续(注意是继续)开始,提了裤子不认人?不存在的...只不过说进程上下文切换,说到底是操作系统完成,而且好像也没有什么API接口之类的可以让我们直接使用这个功能,而这个yield似乎在用户态就实现了这个功能,于是这就给了我们一种搞骚操作的一种可能性。 上面的demo里,我们已经接触了Generator生成器的好几个方法,比如valid()、current()、next()等,然后我们再说一个更重要的方法:send()。 ```php send( "外部发送给Generator:".$generator->current() * 10 ); ``` 愉快的跑一波儿: ![](https://ti-node.com/static/upload/PNP/a/img_11.png#width-full) 这个send()使得我们拥有另外一个能力:与Generator进行数据交互。此前的demo都是我们从Generator中获取数据,现如今send()方法可以向Generator发射数据,这就叫持枪互射。 上面代码我们xue微改一下,然后我改你们猜,猜下结果好乏? ```php send( "外部发送给Generator:".$generator->current() * 10 ); } ``` . . . . . . . . . . . . 猜好了?我揭锅了昂... ...啦啦啦~~~ ![](https://ti-node.com/static/upload/PNP/a/img_12.png#width-full) 很明显,这个一定大概率地诠释了什么叫意外、什么叫惊喜。相对于喜当爹那种意外和惊喜,yield Generator这种惊喜在意外中又带着一丝丝理性逻辑的拷问。 意外与惊喜 人在家中坐,女神忽叫我; 问女神啥事,女神欲还说; 问女何所思,女神掩面泣; 问女何所忆,女神哭啼啼; 我若嫁于你,你愿共伴离? 如若愿嫁我,我一生相许; 女神破涕笑,笑颜恍若桃; 明到你住所,你休要欺我~ 我内心荡漾,然表面逞强。 ... .. . 那个,咳咳,不好意思跑题了跑题了,今天先编到这儿,明天我再发yield Generator的第二篇接着写完这首诗,这个即兴发挥有点儿收不住了。 接着说上面demo为啥会出现这种情况呢?最早的那会儿,大概一两年前吧,我一直以为这是一个bug,后来才发现实际上并不是,这个是一个预期的行为,具体说就是当你调用Generator的send()时,会自动触发一次next()。 yield基础使用方法普及完毕,明天第二篇开始应用。