14 Generator
Generator
就是可以返回多个结果,也是支持 Iterator 接口.
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
也就是 可以直接返回 iterator 接口.
retrun 直接 done:true
Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。本章详细介绍Generator函数的语法和API,它的异步编程应用请看《异步操作》一章。
特别的东西
由于Generator函数返回的遍历器对象,只有调用
next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。由于Generator函数返回的遍历器对象,只有调用
next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。遍历器对象的
next方法的运行逻辑如下。(1)遇到
yield语句,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。(2)下一次调用
next方法时,再继续往下执行,直到遇到下一个yield语句。(3)如果没有再遇到新的
yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。(4)如果该函数没有
return语句,则返回的对象的value属性值为undefined。
举个例子就是
function* helloWorldGenerator() {
console.log('0')
yield 'hello';
console.log('1')
yield 'world';
console.log('2')
return 'ending';
}
var hw = helloWorldGenerator();
//输出结果
hw.next()
0
Object {value: "hello", done: false}
hw.next()
1
Object {value: "world", done: false}
hw.next()
2
Object {value: "ending", done: true}
这就是 yield 暂停.
应用场景
异步操作的同步化表达
function* main() {
var result = yield request("http://some.url");
var resp = JSON.parse(result);
console.log(resp.value);
}
function request(url) {
makeAjaxCall(url, function(response){
it.next(response);
});
}
var it = main();
it.next();
控制流管理
function* longRunningTask(value1) {
try {
var value2 = yield step1(value1);
var value3 = yield step2(value2);
var value4 = yield step3(value3);
var value5 = yield step4(value4);
// Do something with value4
} catch (e) {
// Handle any error from step1 through step4
}
}
function *doStuff() {
yield fs.readFile.bind(null, 'hello.txt');
yield fs.readFile.bind(null, 'world.txt');
yield fs.readFile.bind(null, 'and-such.txt');
}
for (task of doStuff()) {
// task是一个函数,可以像回调函数那样使用它
}
Next 参数
这玩意儿蛮好玩的.
yield句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
这个例子就很好地说明了问题.
以第二次为例子
b.next()
return x + 1
b.next(12)
var y = 2 * 12
return y / 3 = 8
b.next(13)
var z = 13;
24 + 13 + 5 = 42.
就是这样
return
可以强行终止 Generator 函数.
function* a() {
yield 1;
yield 2;
yield 3;
yield 4;
}
o.next() 1
o.return('cao') cao
o.next() undefined
yield*
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
yield 'a';
yield 'b';
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
for (let v of foo()) {
yield v;
}
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// "x"
// "a"
// "b"
// "y"
一个例子。
function* objectEntries(obj) {
let propKeys = Reflect.ownKeys(obj);
for (let propKey of propKeys) {
yield [propKey, obj[propKey]];
}
}
let jane = { first: 'Jane', last: 'Doe' };
for (let [key, value] of objectEntries(jane)) {
console.log(`${key}: ${value}`);
}
另一个例子,遍历二叉树
// 下面是二叉树的构造函数,
// 三个参数分别是左树、当前节点和右树
function Tree(left, label, right) {
this.left = left;
this.label = label;
this.right = right;
}
// 下面是中序(inorder)遍历函数。
// 由于返回的是一个遍历器,所以要用generator函数。
// 函数体内采用递归算法,所以左树和右树要用yield*遍历
function* inorder(t) {
if (t) {
yield* inorder(t.left);
yield t.label;
yield* inorder(t.right);
}
}
// 下面生成二叉树
function make(array) {
// 判断是否为叶节点
if (array.length == 1) return new Tree(null, array[0], null);
return new Tree(make(array[0]), array[1], make(array[2]));
}
let tree = make([[['a'], 'b', ['c']], 'd', [['e'], 'f', ['g']]]);
// 遍历二叉树
var result = [];
for (let node of inorder(tree)) {
result.push(node);
}
result
// ['a', 'b', 'c', 'd', 'e', 'f', 'g']
14 Generator的更多相关文章
- [Advanced Python] 14 - "Generator": calculating prime
高性能编程 几个核心问题 • 生成器是怎样节约内存的?• 使用生成器的最佳时机是什么?• 我如何使用 itertools 来创建复杂的生成器工作流?• 延迟估值何时有益,何时无益? From: htt ...
- [ES6] 14. Generator -- 1. yield & next()
Generators in ECMAscript 6 are first-class coroutines that produce encapsulated suspended execution ...
- 2016.7.14 generator基于注解和基于xml自动生成代码的区别
1.generator配置文件generatorConfig.xml的区别 2.生成代码的区别 注:二者的实体类都一样. (1)基于XML 生成的文件有: 后面省略. 也就是说,基于xml的方式,是要 ...
- ES6生成器函数generator
ES6生成器函数generator generator是ES6新增的一个特殊函数,通过 function* 声明,函数体内通过 yield 来指明函数的暂停点,该函数返回一个迭代器,并且函数执行到 y ...
- Hibernate:如何映射聚合?
Hibernate:如何映射聚合? 目录 背景映射聚合聚合模型映射配置测试备注 背景返回目录 DDD 是在 Hibernate 之后发现的概念,Hibernate 如何映射 DDD 中的聚合呢?本文给 ...
- Hibernate乐观锁和悲观锁
Hibernate支持两种锁机制: 即通常所说的"悲观锁(Pessimistic Locking)"和 "乐观锁(OptimisticLocking)". 悲观 ...
- [Python] 03 - Lists, Dictionaries, Tuples, Set
Lists 列表 一.基础知识 定义 >>> sList = list("hello") >>> sList ['h', 'e', 'l', ' ...
- Nutch学习笔记二——抓取过程简析
在上篇学习笔记中http://www.cnblogs.com/huligong1234/p/3464371.html 主要记录Nutch安装及简单运行的过程. 笔记中 通过配置抓取地址http://b ...
- Nutch学习笔记一 ---环境搭建
学习环境: ubuntu 概要: Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. 通过nutch,诞生了hadoop.tika ...
随机推荐
- JavaScript基本数据类型和引用数据类型
ECMAScript包含两种不同数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据段,而引用类型值那些可能有多个值构成的对象. 在进行变量赋值时,解析器必须确定这个值是基本类型值还是引用 ...
- xamarin 一般错误解决办法
1. android_m2repository_r错误 问题描述: Unzipping failed. Please download https://dl-ssl.google.com/androi ...
- JSPatch来更新已上线的App中出现的BUG(超级详细)
JSPatch的作用是什么呢? 简单来说:(后面有具体的操作步骤以及在操作过程中会出现的错误) 1.iOS应用程序上架到AppStore需要等待苹果公司的审核,一般审核时间需要1到2周.虽然程序在上架 ...
- Tomcat中的Session小结
什么是Session 对Tomcat而言,Session是一块在服务器开辟的内存空间,其存储结构为ConcurrentHashMap: Session的目的 Http协议是一种无状态协议,即每次服务端 ...
- android EditText 默认情况下不获取焦点(不弹出输入框)
可以在EditText前面放置一个看不到的LinearLayout,让它率先获取焦点: <LinearLayout android:focusable="true" andr ...
- SqlServer SET IDENTITY_INSERT ON | OFF
想要将值插入到自动编号(或者说是标识列,IDENTITY)中去,需要设定 SET IDENTITY_INSERT 示例: 1.首先建立一个有标识列的表: )) 2.尝试在表中做以下操作: , 'gar ...
- 刚接触Linux,菜鸟必备的小知识点(一)
身为一个将要大四的学生,而且还是学计算机的没有接触过linux简直是羞愧难当.这个假期做了一个软件测试员,必须要熟悉linux的操作,所以对于我这个菜鸟我也就说几点比较重要的小知识点吧. 第一.cd指 ...
- java基础学习03(java基础程序设计)
java基础程序设计 一.完成的目标 1. 掌握java中的数据类型划分 2. 8种基本数据类型的使用及数据类型转换 3. 位运算.运算符.表达式 4. 判断.循环语句的使用 5. break和con ...
- Resources.Load加载文件返回null的原因
1.文件夹都要放在Resources目录下 2.加载时photoName不需要扩展名 Texture2D t = Resources.Load<Texture2D>("Loadi ...
- Maven学习
http://www.cnblogs.com/sprinng/p/5141233.html 生成项目jar包失败 maven安装出现解决:http://blog.csdn.net/kjfcpua/ar ...