Generator
Generator
函数是ES6
提供的异步编程的解决方案。它和普通的函数有第一定的区别。 在普通函数后面加上一对括号那么普通函数会执行并返回结果。 而Generator
函数并不执行, 它返回的也不是运行结果, 而是一个遍历器对象.
yield和next
yield
用来暂停后面的操作, 我们可以使用next
方法进行取值.
next
方法返回的是一个对象,这个对象有连个属性: value
和done
, value
表示此次的值, done
表示是否结束函数.
//next返回一个对象
//value值: 上一个yield后面的值作为value值(注意不是yield的返回值)
//done表示是否结束, true表示结束
function* gene() {
yield 1
yield 2
return 3
}
var gg = gene() //返回遍历器对象
gg.next() //{value: 1, done: false}
gg.next() //{value: 2, done: false}
gg.next() //{value: 3, done: true}
通过next
移动指针, 移向下一个状态. 即yield
.
yield
后面的值是next
对象中的value
值yield
的返回值是undefined
function* gen() {
var a = yield 1
console.log('a')
console.log(a)
var b = yield a+1
console.log('b')
console.log(b)
return 3
}
var g = gen()
g.next()
//{value: 1, done: false}
g.next() //不给next传值,上一次yield就返回undefined,也即a为undeinfed. value为undefined+1得到NaN
/*
a
undefined
{value: NaN, done: false}
*/
g.next() //不给next传值,上一次yield就返回undefined,也即c为undeinfed
/*
b
undefined
{value: 3, done: true}
*/
- 若给
next
传参, 则next
参数是上一次的yield
的值
//next的参数是上一次yield的值
var ge = gen()
ge.next()
//{value: 1, done: false}
/*
上一次yield返回值为10并赋值给a,a也为10。value为这次yield后面的值即a+1
*/
ge.next(10)
/*
a
10
{value: 11, done: false}
*/
/*
next参数为空, 则上一次yield返回值为undefined并赋值给b, 则b为undefined
*/
ge.next()
/*
b
undefined
{value: 3, done: false}
*/
return
return
函数是Generator.prototype
上的函数. 它的作用是结束Generator
函数并返回. 可以给人return
传送一个参数1
表示返回值. 此时返回的对象是
{value: 1, done: true}
done
为true
表示函数结束, 即使函数没有执行完毕.
//代码来自阮一峰的教程
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
//正常结束
g.next(); // { value: 1, done: false }
g.next(); // { value: 2, done: false }
g.next(); // { value: 3, done: true }
//return结束
g.next(); // { value: 1, done: false }
g.return("foo"); // { value: "foo", done: true }
g.next(); // { value: undefined, done: true }
上例中, 执行g.return('foo')
结束Generator
函数的执行, 可以看到value
值为foo
, done
为true
. 对比正常结束, 可以看清区别.
throw
Generator.prototype.throw
用来向生成器抛出异常,并恢复生成器的执行,返回带有 done
及 value
两个属性的对象。
通过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
第一个throw
被内部捕获, 此时内部抛出异常. 第二次抛出的异常是由外部的catch
抛出的. 因为内部的catch
已经执行过一次了, 而且内部没有更多的catch
用于捕获第二次异常, 则第二次异常会被外部捕获.