php 协程 generator中的yield实现协程

简单讲述一下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!...

猜你喜欢

转载自blog.csdn.net/gaoxuaiguoyi/article/details/74298769