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. SQL - 先安装SQL2008 R2后安装AD导致无法正常登陆数据库(无法启动MSSQLSERVER)

    分析原因:安装AD后,系统改为使用域用户登陆,原先安装SQL时设置的“本地用户”信息已经修改,当前(域)用户没有权限访问MSSQLSERVER实例文件夹或整个SQL文件夹. 解决方法: 1.打开“服务 ...

  2. Eclipse 中设置JVM 内存

    Eclipse 中设置JVM 内存 今天在eclipse 中测试把文档转换为图片的时候,报出了下面的错误: java.lang.OutOfMemoryError: Java heap space 从上 ...

  3. Hadoop windows 环境配置

    下载 winutils 点击 这里下载 winutils 包,并解压缩. 此处解压缩后目录位置为 D:\software\hadoop2.6 配置环境变量 变量名 变量值 HADOOP_USER_NA ...

  4. RestfulAPI超简单入门

    简单入门 REST -- REpresentational State Transfer,英语的直译就是"表现层状态转移" 是目前最流行的 API 设计规范,用于 Web 数据接口 ...

  5. PHP获取本周的每一天的时间

    1.PHP获取未来一周的时间 public function getWeek() { for($i=0;$i<7;$i++) { $arr[$i]=date('Y-m-d',strtotime( ...

  6. 【代码笔记】iOS-UIAlertView自动关闭

    一,效果图. 二,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController : UIVi ...

  7. 在vue项目中,通过v-for循环,动态添加后台返回的事件

    一.现有一种业务需求,前端的某个元素添加点击事件,但事件是后台返回的(不确定),需要动态添加,下面是具体思路: .假定后台返回数据为如下格式: list: [ { name: '李寻欢', kungF ...

  8. Nodejs编译Native Code:使用C++构建工具npm

    Nodejs的很多NPM包需要本地编译,通常是C++写的代码,例如图像处理模块等. 这是如果生产环境没有安装Visual Studio 2015等开发工具,通常会编译失败,发现了一个npm专门干这事儿 ...

  9. Android Relative Layout 安卓相对布局详解

    思维导图可在幕布找到 1. 基础 如果在相对布局里,控件没有指明相对位置,则默认都是在相对布局的左上角: <TextView android:layout_width="wrap_co ...

  10. hashCode()与equals()方法的对比

        Java对于eqauls方法和hashCode方法是这样规定的: 1.如果两个对象相同,那么它们的hashCode值一定要相同: 2.如果两个对象的hashCode相同,它们并不一定相同(上面 ...