Generator函数是ES6提供的一种异步编程解决方案,普通函数一旦执行,除非遇到return,不然就一直往下运行,也不能从外部再传值进入函数体。而Generator函数,运行期间是可以打断。它相对于普通函数,有如下特征
-
function关键字和函数名之间有个" * "号
function* generator(){} -
在函数体内可以使用yield关键字,把函数的执行流程挂起。如果用在另一个表达式中,必须放在圆括号里面。在一个Generator函数里面执行另一个Generator函数,前面也要加关键字
function* generator(){ yield 'status' console.log('abc' + (yield def)) return 'hello' } function* gen(){ yield generator() } -
调用generator函数,不会返回运行结果,而是返回一个遍历器对象。这个对象有next方法和return方法。
function* generator(){ yield 'status 1' yield 'status 2' return 'hello' } console.log(generator()) //generator {<suspended>} const obj = generator() obj.next() // {value: "status 1", done: false} obj.next() // {value: "status 2", done: false} obj.next() // {value: "hello", done: true} ,true 表示所有状态都遍历完毕 obj.next() // {value: undefined, done: true} , 没有状态返回值了,所以返回undefined //如果使用return方法,则返回值,并结束遍历 obj.return('abc') //{value:'abc', done: true} ,如果不传参,则返回undefined /** next方法也可以传参,next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时, 传递参数是无效的。所以第一次调用无需传入参数 **/ function* gen(x) { let y = 1 + (yield (x + 1)) let z = yield (y + 1) return x + y + z } const it = gen(5) console.log(it.next()) //{value: 6, done: false} console.log(it.next(9)) //{value: 11, done: false} console.log(it.next(2)) //{value: 17, done: true} /** 解析一下上面的执行流程 第一次执行,暂停返回x+1,也就是6。 第二次执行,上次暂停的地方开始执行,传入的参数是9,也就是1+9,y=10,然后暂停返回10+1,也就是11 第三次执行,还是从上次的地方开始,传入的是2,z=2,return 5 + 10 + 2 ,也就是17 **/ //循环取值的方法 function* gen() { yield 1 yield 2 return 3 } for(let item of gen()) { console.log(item) // 1 2 ,done属性为true时,终止循环,并且不会返回值 }