一、Generator生成器函数
它是ES6新推出的一种异步编程解决方案,与普通函数的区别:函数名前多了一个星号,与yield关键字配合使用,实现暂停执行的功能。
1. 特点
- 函数名前多了一个星号*
- 直接调用 Generator函数并不会执行,也不会返回运行结果,而是返回一个遍历器对象(Iterator Object)
- 依次调用遍历器对象的next方法,遍历 Generator函数内部的每一个状态
- 函数体内使用 yield,定义不同的内部状态 ,会暂停执行
例如:
以下是一个生成器函数
function *generator(x) {
console.log('x', x);
}
此时我们直接执行generator(10)
发现竟然什么也没输出?说明根本没有执行console.log(x,'x’)
所以我们应该着重注意generator函数的特点:
generator返回的是一个遍历器对象;
调用遍历器对象的next才可以执行函数;
function *generator(x) {
console.log('x', x);
}
const a = generator(10);
a.next();
当我们用一个变量接住generator返回的遍历器对象,并调用next方法,就执行了console语句!
生成器函数的执行就像挤牙膏,被人挤一下才出来一点
2. 关联概念
二、yield的加入
1. 引入
在上面的例子新增两个语句,其中一句是yield表达式,一个是正常的log语句
function *generator(x) {
console.log('x', x);
let b = yield x; //新增语句
console.log('b', b) //新增语句
}
let a = generator(10);
console.log(a.next());
让我们来看看结果是什么?
与上述例子相同的是仍然输出了x 10
,但是第二个console并没有被执行,反而返回了一个对象{value:10, done:false}
==推断=>
程序的执行已经卡在yield语句那一行并且返回了一个对象
2. yield 特点
yield的返回是一个对象,包括 value 和 done 两部分:
- value:返回值
- done:generator函数是否执行完。false表明该函数后续还有可以执行的部分,反之则无
并且当在generator函数执行中遇到yield就会中断,只有进行下一次next()
才会执行下一段代码(下一个yield之前的一段)
三、举个例子
function *generator(x) {
console.log('x', x);
let b = yield x; //第一次next执行到此行
console.log('x_after', x);
console.log('b', b);
yield "hello"; //第二次next执行到此行
console.log('end');
}
let a = generator(10);
console.log(a.next());
console.log(a.next(1000));
结果:
-
第二次调用next执行的语句块是两个yield之间的内容
-
调用next()时,传入一个值1000:
再次打印x,x的值仍未10。但用b接收yield语句,b变为1000,说明 next()传进去的值会被yield接收作为自己的值,并可以返回给接收的变量。