概念:可以把Generator 函数理解成状态机(封装了多个内部状态)或者是一个遍历器对象生成函数
写法:Generator函数的定义跟普通函数差不多,只是在function关键字后面加了一个星号
function* test(){
yield 'hello';
yield 'world';
return 'done'
} var te = test(); //什么都没有
te.next(); //{ value: 'hello', done: false }
te.next(); //{ value: 'world', done: false }
te.next(); //{ value: 'done', done: true }
te.next(); //{ value: undefined, done: true }
说明:1)不管内部有没有yield语句,调用Generator函数,该函数并不立即执行,也不返回函数执行结果,而是返回一个指向内部状态的generator对象,也可以看作是一个遍历器对象。
2)必须调用该对象的next方法,让函数继续走下去,使指针移向下一个状态。每当碰到yield语句,内部指针就停下来,直到下一次调用next()才开始执行。
3)如果没有再遇到yield 则返回return的值为value的属性值
4)如果没有return表达式,则将undefined作为value的属性值
5)Generator函数中可以没有yield表达式,此时,Generator函数表示一个暂缓执行函数
Generator函数的next()方法:(next方法内可以传入参数,传入的参数将作为上一个yield表达式的返回值(意思是第一个next传入参数无效))
function* gen(a) {
let b = yield (a + 1);
return b * 2;
}
let g = gen(1);
g.next(); // Object {value: 2, done: false}
g.next(); // Object {value: NaN, done: true}
let ge = gen(1);
ge.next(); // Object {value: 2, done: false}
ge.next(3); // Object {value: 6, done: true}
上面第二次调用g.next()返回的value为NaN而不是2*2,说明yield表达式没有返回值,或者说yield表达式总是返回undefined
for...of遍历Generator函数内的状态:
function *foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
} for (let v of foo()) {
console.log(v);
}
// 1 2 3 4 5
return语句不会被遍历
yield* 表达式(用来在一个 Generator 函数里面执行另一个 Generator 函数。)
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// "x" "a" "b" "y"
Generator函数的异步编程:
- 异步函数的同步实现
function* loadUI() {
showLoadingScreen();
yield loadUIDataAsynchronously();
hideLoadingScreen();
}
var loader = loadUI(); //这一步什么都不执行
loader.next() //执行函数showLoadingScreen()和loadUIDataAsynchronously()
loader.next() //执行函数hideLoadingScreen
- 流程控制
function* execute() {
let value1;
let value2;
let value3;
let value4;
yield value1 = step1();
yield value2 = step2(value1);
yield value3 = step3(value2);
yield value4 = step4(value3);
console.log(value4);
}
function step1() {
return `step1_start`;
}
function step2(value) {
return `step2_${value}`;
}
function step3(value) {
return `step3_${value}`;
}
function step4(value) {
return `step4_${value}`;
} for(var item of execute()); //step4_step3_step2_step1_start
注意:yield总是返回undefined,但此处并不是直接返回yiled,而是给yield后面的变量赋值,故能运算