generator内部有异常时的执行机制
执行generator函数会返回一个iterator,iterator调用next
方法会返回一个值。如果next
执行过程中出现异常是否还会返回值呢?如果返回值的话,会返回那个值呢?
情况一:捕获的异常
main
generator内出现了一个被捕获的异常。
function *main(){
yield 1;
try{
undefinedValue.sayHello();// 这里会出现ReferenceError
yield 2;
}catch(e){
console.log('捕获了异常');
}
yield 3;
return 4;
}
var it=main();
it.next();
// {value: 1, done: false}
it.next();
// 捕获了异常
// {value: 3, done: false}
it.next();
// {value: 4, done: true}
第二个next
方法被调用时,打印了“捕获了异常”的字样,并返回了 {value: 3, done: false}
。说明yield 2
被跳过,并执行yield 3
。
情况二:未捕获的异常
main
generator内出现了一个未被捕获的异常。
function *main(){
yield 1;
undefinedValue.sayHello();// 这里会出现ReferenceError
yield 2;
yield 3;
return 4;
}
var it=main();
it.next();
// {value: 1, done: false}
it.next()
console.log('测试是否会打印')
// Uncaught ReferenceError: undefinedValue is not defined
// at main (<anonymous>:4:5)
// at main.next (<anonymous>)
// at <anonymous>:1:4
it
// main {<closed>}
第二个next
方法被调用时直接抛出了异常,并且后面的console.log('测试是否会打印')
没被执行。再次查看it
时,发现它的状态变成了closed
。
情况三:通过iterator的throw
方法产生的异常
我们在第二个next
方法之后调用iterator的throw
方法产生一个异常,该异常刚好被try..catch
捕获。
function *main(){
yield 1;
try{
yield 2;
yield 3;
}catch(e){
console.log(e);
}
yield 4;
return 5;
}
var it=main();
it.next();
// {value: 1, done: false}
it.next();
// {value: 2, done: false}
it.throw('异常');
// 异常
// {value: 4, done: false}
it.next();
// {value: 5, done: true}
我们在第二个next
方法后面调用iterator的throw
方法产生一个异常,此时的异常出现在yield 2
的位置,并被try..catch
捕获处理,所以程序跳过了yield 3
执行了yield 4
。
总结
如果generator’s iterator调用next
的过程中遇到被捕获的异常,它处理完异常后会继续运行,直到碰到yield
return
或函数的结尾。如果遇到的是未被捕获的异常,它将抛出异常,并且iterator的状态变为closed
。通过iterator的throw
方法产生的异常和普通的异常是一样的执行逻辑。