php 协程 generator中的yield实现协程

来源:互联网 发布:tom大叔 javascript 编辑:程序博客网 时间:2024/06/14 09:01

简单讲述一下php里面的协程支持。


<?php//yield是干什么的?//当程序运行到yield的时候,当前程序就唤起协程记录上下文。function num(){for ($i=1;$i<10;$i++){yield $i;}}foreach(num() as $n){echo $n."\n";}//当然还可以这样function printer() {while (true) {$string = yield;echo $string;}}$printer = printer();$printer->send("Hello world! \n");//Generator 是干什么的,Generator 是迭代器,实现了Iterator 接口/*    //官方的代码    <?php        class Generator implements Iterator {            public function rewind();          // Rewinds the iterator. If                                               // iteration has already begun,                                               // this will throw an exception.            public function valid();           // Returns false if the                                               // iterator has been closed.                                               // Otherwise returns true.            public function current();         // Returns the yielded value.            public function key();             // Returns the yielded key.            public function next();            // Resumes execution of the                                               // generator.                        public function send($value);      // Sends the given value to the                                               // generator as the result of                                               // the yield expression and                                               // resumes execution of the                                               // generator.        }        ?> *///利用Generator写一个中间件,类似于laravel框架的中间件function MyMiddleware($middleware = []){$stack = [];foreach ($middleware  as $mid){$handle = call_user_func_array($mid,[]);$stack[] = $handle;$handle->current();}while($handle = array_pop($stack)){$handle->send("ok! \n");$handle->next();}}function one(){echo "this is one start \n";$a = yield;echo $a;echo "this is one end \n";}function two(){echo "this is two start \n";$a = yield;echo $a;echo "this is two end \n";}MyMiddleware(['one','two']);//再列举一个生产 和 消费者直接的例子 加以说明function consumer(){while (true){$n = yield;if(!$n){return;}echo '[CONSUMER] Consuming'.$n.'...'."\n";sleep(1);$msg = '200,ok!';yield $msg;}}function produce(Generator $generator){$n = 0;while ($n < 5){$n ++;echo '[PRODUCER] Producing '.$n.'...'."\n";$generator->send($n);$msg = $generator->current();$generator->next();echo '[PRODUCER] Consumer return: '.$msg.'...'."\n";}}$c = consumer();produce($c);/** * 解释 * 启动生成器 * 然后,一旦生产了东西,通过$generator.send($n)切换到consumer执行 * consumer通过yield拿到消息,处理,又通过yield把结果传回 * produce拿到consumer处理的结果,继续生产下一条消息 * 直到produce结束 */

以上代码可以直接拷贝到本地使用php 命令运行。

输出结果:

D:\myapache\www\demo\middleware>php demo.php
1
2
3
4
5
6
7
8
9
Hello world!
this is one start
this is two start
ok!
this is two end
ok!
this is one end
[PRODUCER] Producing 1...
[CONSUMER] Consuming1...
[PRODUCER] Consumer return: 200,ok!...
[PRODUCER] Producing 2...
[CONSUMER] Consuming2...
[PRODUCER] Consumer return: 200,ok!...
[PRODUCER] Producing 3...
[CONSUMER] Consuming3...
[PRODUCER] Consumer return: 200,ok!...
[PRODUCER] Producing 4...
[CONSUMER] Consuming4...
[PRODUCER] Consumer return: 200,ok!...
[PRODUCER] Producing 5...
[CONSUMER] Consuming5...
[PRODUCER] Consumer return: 200,ok!...