generator错误捕获取决于当前执行位置:刚创建时throw()等效next()可被捕获,停在yield时只影响后续同步代码,执行完毕后throw()直接拒绝;错误不跨yield穿透。

Generator 内部错误处理的关键在于:错误必须在生成器当前执行位置能被 try...catch 捕获,且 throw() 方法只能影响“下一个暂停点之前”的同步代码段。它不是全局广播,也不跨 yield 穿透。
throw() 方法的触发时机与限制
generator.throw(error) 向生成器内部抛出错误,但能否被捕获,取决于生成器当前所处的状态:
- 生成器刚创建、尚未调用
next():此时throw()会像首次next()一样进入函数体开头,可被函数最外层的try...catch捕获 - 生成器正停在某个
yield处(done: false):错误会立即注入该暂停点之后、下一次yield或return之前的同步执行路径中,若此处有try...catch就能捕获 - 生成器已执行完毕(
done: true):再调用throw()会直接拒绝,无法被内部捕获,而是以未处理异常形式抛出到外部 - 错误不会“跳过”yield:比如在
yield 1和yield 2之间抛错,只能影响这两句之间的代码;它不会让yield 2自动跳过或中断后续流程
在生成器函数内使用 try…catch 捕获 throw()
你可以在生成器函数体内写标准的 try...catch,但它只对发生在该 try 块内的同步代码有效——包括 throw() 注入的错误(只要注入点落在块内)。
例如:
function* safeGenerator() {
try {
yield 'start';
// 此处可能被 throw() 中断
console.log('after first yield');
yield 'middle';
} catch (e) {
console.log('caught:', e.message);
yield 'error handled';
}
yield 'end';
}
调用过程:
-
gen.next()→{ value: 'start', done: false } -
gen.throw(new Error('oops'))→ 进入catch,输出日志,并产出'error handled' -
gen.next()→{ value: 'end', done: false }
return() 与 throw() 的行为对比
两者都是向生成器发送控制信号,但语义和错误传播逻辑不同:
-
generator.return(value):强制结束生成器,返回{ value, done: true };不触发任何catch,也不会中断正在执行的同步逻辑 -
generator.throw(error):模拟一个同步错误发生在当前执行点,会沿调用栈向上冒泡,直到遇到匹配的catch;若无捕获,则外部会收到Uncaught [Error] - 注意:
return()不会清空未完成的try...finally块,而throw()会正常触发finally(只要错误没被上层吞掉)
常见误用与规避建议
实际开发中容易踩的坑:
- 在
yield表达式后直接写catch:无效。因为yield是暂停点,错误注入后执行流未必经过你写的catch块 —— 必须把try...catch包裹住可能出错的同步区段 - 多次
throw()后继续next():一旦生成器因throw()进入catch并执行完,后续next()仍按正常流程走;但如果throw()导致生成器退出(如catch里又return或抛新错),再调用next()就返回{ value: undefined, done: true } - 混淆
throw()和普通throw:函数体内写throw new Error()是同步抛错,由 JS 引擎立即处理;generator.throw()是外部主动注入,时机由调用者控制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











