Generator 函数是 ES6 提供的一种异步编程解决方案
Generator 函数看是跟普通函数一样,但是有两个特征:
1. function 与 函数名之间有 一个 “*”(星号)
2. 函数内部使用 yield 语句
function* Ge(){
console.log('setp1');
yield 'setp1 over';
console.log('step2');
yield 'step2 over';
console.log('step3');
return 'end'
}
var s=Ge()
s.next()
//setp1
//{ value: 'setp1 over', done: false }
s.next()
//step2
//{ value: 'step2 over', done: false }
s.next()
//step3
//{ value: 'end', done: true }
调用遍历器对象的next方法,使得指针移向下一个状态
即每次调用使用 next方法
可以理解为遇到yield是暂停,next继续执行
每次next 都会返回一个{value:”,done:”}的对象想
使用注意:
* yield语句如果用在一个表达式之中,必须放在圆括号里面
* yield 作为函数的参数可以不加括号
与 Iterator 接口的关系
Generator函数就是遍历器生成函数
给对象赋值 Symbol.iterator属性 ,该对象具有 Interator 接口
var obj[Symbol.iterator] = function* (){
yield 1;
yield '2';
yield true;
};
//[Function]
[...obj]
//[ 1, '2', true ]
next 方法的参数
yield 句本身没有返回值,或者返回值为 undefined
next 可以带一个参数 ,该参数会被当做上一yield 的返回值
function* f() {
for(var i = 0; true; i++) {
var reset = yield i;
console.log('i=='+i);
console.log('reset=='+reset);
if(reset) { i = -1; }
}
}
var r = f()
r.next()
//{ value: 0, done: false }
r.next()
//i==0
//reset==undefined
//{ value: 1, done: false }
r.next(true)
//i==1
//reset==true
//{ value: 0, done: false }
Generator.prototype.throw()
Generator函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在Generator函数体内捕获。
var g = function* () {
try {
yield;
} catch (e) {
console.log('内部捕获', e);
}
};
var i = g();
i.next();
try {
i.throw('a');
i.throw('b');
} catch (e) {
console.log('外部捕获', e);
}
//内部捕获 a
//外部捕获 b
一旦Generator执行过程中抛出错误,且没有被内部捕获,就不会再执行下去了
Generator.prototype.return()
Generator函数,return方法可以返回给定的值,并终结遍历Generator函数
调用 Generator 的return 方法后 返回值就return的参数 “done”的值“true”;终结Generator函数,再调用next 是 “value”为“undefined”
return 可以重设 “value”值
g.next()
//{ value: 1, done: false }
g.return('ok')
//{ value: 'ok', done: true }
g.next()
//{ value: undefined, done: true }
g.return('no')
//{ value: 'no', done: true }
需要注意的是 如果Generator函数内部有try…finally代码块,那么return方法会推迟到finally
function* ge() {
try{
yield '1';
yield '2';
yield '3';
}finally{
yield '4'
yield '5'
}
}
var g = ge();
g.next()
//{ value: '1', done: false }
g.return('foo')
//{ value: '4', done: false }
g.next()
//{ value: '5', done: false }
yield*
默认条件下在Generator 函数内部 调用另一个Generator 函数 是无效的
function* a(){
yield 'a1';
yield 'a2';
b();
yield 'a3';
}
function* b(){
yield 'b1';
yield 'b2';
yield 'b3';
}
g.next()
//{ value: 'a1', done: false }
g.next()
//{ value: 'a2', done: false }
g.next()
//{ value: 'a3', done: false }
g.next()
//{ value: undefined, done: true }
///
function* a(){
yield 'a1';
yield 'a2';
yield* b();
yield 'a3';
}
function* b(){
yield 'b1';
yield 'b2';
yield 'b3';
}
var g=a();
g.next()
//{ value: 'a1', done: false }
g.next()
//{ value: 'a2', done: false }
g.next()
//{ value: 'b1', done: false }
g.next()
//{ value: 'b2', done: false }
g.next()
//{ value: 'b3', done: false }
g.next()
//{ value: 'a3', done: false }
g.next()
//{ value: undefined, done: true }
yield* 后面一个数组,或支持遍历器的数据结构 都可以对其遍历
Generator函数的this
Generator函数总是返回一个遍历器,ES6规定这个遍历器是Generator函数的实例,也继承了Generator函数的prototype对象上的方法
Generator 的实例的this 返回的 总是遍历对象
解决方案
function* ge(){
this.a='a';
this.b=function (){
console.log('b')
};
yield '1';
yield '2';
yield '3';
}
function Ge(){
return GeneratorFn.call(GeneratorFn.prototype)
}
var g = new Ge()