概念:可以把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后面的变量赋值,故能运算