1、Generator 
Generator , 一种可以返回迭代器的生成器,当程序运行到yield的时候,当前程序就唤起协程记录上下文,然后主函数继续操作,当需要操作的时候,在通过迭代器的next重新调起

function xrange($start, $end, $step = 1) {
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}
foreach (xrange(1, 1000) as $num) {
echo $num, "\n";
}
/*
* 1
* 2
* ...
* 1000
*/

如果了解过迭代器的朋友,就可以通过上面这一段代码看出Generators的运行流程

Generators::rewind() 重置迭代器
Generators::valid() 检查迭代器是否被关闭
Generators::current() 返回当前产生的值
Generators::next() 生成器继续执行
Generators::valid()
Generators::current()
Generators::next()
...
Generators::valid() 直到返回 false 迭代结束

2、Generator应用 
很多不了解的朋友看完可能会表示这有什么用呢?

举个栗子: 
比如从数据库取出数亿条数据,这个时候要求用一次请求加响应返回所有值该怎么办呢?获取所有值,然后输出,这样肯定不行,因为会造成PHP内存溢出的,因为数据量太大了。如果这时候用yield就可以将数据分段获取,理论上这样是可以取出无限的数据的。

一般的获取方式 :

数据库连接.....
$sql = "select * from `user` limit 0,500000000";
$stat = $pdo->query($sql);
$data = $stat->fetchAll(); //mysql buffered query遍历巨大的查询结果导致的内存溢出
var_dump($data);

yield获取方式:

数据库连接.....
function get(){
$sql = "select * from `user` limit 0,500000000";
$stat = $pdo->query($sql);
while ($row = $stat->fetch()) {
yield $row;
}
}
foreach (get() as $row) {
var_dump($row);
}

3、Generator::send

  1. 向生成器中传入一个值,并且当做 yield 表达式的结果,然后继续执行生成器。
  2. 如果当这个方法被调用时,生成器不在 yield 表达式,那么在传入值之前,它会先运行到第一个 yield 表达式。As such it is not necessary to “prime” PHP generators with a Generator::next() call (like it is done in Python)

这代表了什么,这代表了我们可以使用yield进行双向通信

再举个栗子

$ben = call_user_func(function (){
$hello = (yield 'my name is ben ,what\'s your name'.PHP_EOL);
echo $hello;
});
$sayHello = $ben->current();
echo $sayHello;
$ben->send('hi ben ,my name is alex');
/*
* output
*
* my name is ben ,what's your name
* hi ben ,my name is alex
*/

这样ben跟alex他们两个就实现了一次相互问好,在这个例子中我们可以发现,yield跟以往的return不同,它不仅可以返回数据,还可以获取外部返回的数据

而且不仅仅能够send,PHP还提供了一个throw,允许我们返回一个异常给Generator

$Generatorg = call_user_func(function(){
$hello = (yield '[yield] say hello'.PHP_EOL);
echo $hello.PHP_EOL;
try{
$jump = (yield '[yield] I jump,you jump'.PHP_EOL);
}catch(Exception $e){
echo '[Exception]'.$e->getMessage().PHP_EOL;
}
});
$hello = $Generatorg->current();
echo $hello;
$jump = $Generatorg->send('[main] say hello');
echo $jump;
$Generatorg->throw(new Exception('[main] No,I can\'t jump'));
/*
* output
*
* [yield] say hello
* [main] say hello
* [yield] I jump,you jump
* [Exception][main] No,I can't jump
*/

yield协程的更多相关文章

  1. Unity 3D中不得不说的yield协程与消息传递

    1. 协程 在Unity 3D中,我们刚开始写脚本的时候肯定会遇到类似下面这样的需求:每隔3秒发射一个烟花.怪物死亡后20秒再复活之类的.刚开始的时候喜欢把这些东西都塞到Update里面去,就像下面这 ...

  2. 6 生成器 yield 协程

    1.生成器 ----> 1 b = [x*2 for x in range(100000000000)] MemoryError: 想生成一个存放很多数据的列表,但是又不想内存占用太多 每次用一 ...

  3. 20170702-变量说明,静态方法,类方法区别,断点调试,fork,yield协程,进程,动态添加属性等。。

    概念: 并行:同时运行 并发:看似同时运行  json后任然中文的问题 import json d = {"名字":"初恋这件小事"} new_d1 = jso ...

  4. python之 yield --- “协程”

    在编程中我们经常会用到列表,以前使用列表时需要声明和初始化,在数据量比较大的时候也需要把列表完整生产出来,例如要存放1000给数据,需要准备长度1000的列表,这样计算机就需要准备内存放置这个列表,在 ...

  5. 【Unity3D基础教程】给初学者看的Unity教程(五):详解Unity3D中的协程(Coroutine)

    作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 为什么需要协程 在游戏中有许多过程(Proc ...

  6. day-5 python协程与I/O编程深入浅出

    基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1.  什么是协程(以下内容来自维基百 ...

  7. python 进程、线程与协程的区别

    进程.线程与协程区别总结 - 1.进程是计算器最小资源分配单位 - 2.线程是CPU调度的最小单位 - 3.进程切换需要的资源很最大,效率很低 - 4.线程切换需要的资源一般,效率一般(当然了在不考虑 ...

  8. python自动化开发-[第十天]-线程、协程、socketserver

    今日概要 1.线程 2.协程 3.socketserver 4.基于udp的socket(见第八节) 一.线程 1.threading模块 第一种方法:实例化 import threading imp ...

  9. python进阶(二) 多进程+协程

    我们大多数的时候使用多线程,以及多进程,但是python中由于GIL全局解释器锁的原因,python的多线程并没有真的实现 实际上,python在执行多线程的时候,是通过GIL锁,进行上下文切换线程执 ...

随机推荐

  1. .NET Core类库中读取配置文件

    最近在开发基于.NET Core的NuGet包,遇到一个问题:.NET Core中已经没有ConfigurationManager类,在类库中无法像.NET Framework那样读取App.conf ...

  2. SqlServer 使用sys.dm_tran_locks处理死锁问题

    1.模拟资源锁定 --开始事务BEGIN TRANSACTION--更新数据update Table_1 set FuncName=FuncName--等待1分钟WAITFOR DELAY '01:0 ...

  3. JavaScriptDay3

    js对标签的操作 创建标签:document.createElement("tag"); 便签添加内容 : document.createElement("tag&quo ...

  4. 了解java虚拟机—垃圾回收算法(5)

    引用计数器法(Reference Counting) 引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器减1.只要对象A的引用计数器的 ...

  5. Pupu(hdu3003)数论

    Pupu Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  6. RequestDispatcher.forward转发与HttpServletResponse.sendRedirect重定向

    下面是HttpServletResponse.sendRedirect 方法实现的请求重定向与RequestDispatcher.forward 方法实现的请求转发的总结比较:(1)RequestDi ...

  7. jQuery 自动触发事件的坑

    有时候项目需求页面加载完后,需要模拟用户操作,自动点击按钮.Jquery中可以使用trigger()方法模拟事件. $(selector).trigger(event,[param1,param2,. ...

  8. 2016计蒜之道复赛 百度地图的实时路况(Floyd 分治)

    题意 题目链接 Sol 首先一个结论:floyd算法的正确性与最外层\(k\)的顺序无关(只要保证是排列即可) 我大概想到一种证明方式就是把最短路树上的链拿出来,不论怎样枚举都会合并其中的两段,所以正 ...

  9. kotlin3-IdeaIU编辑器字体自动放大缩小

  10. 如何选型商业智能和分析平台,Gartner给了这些建议!

    文 | 水手 在2017年1月20日Gartner发布的<China Summary Translation: 'Survey Analysis: Customers Rate Their BI ...