必须将 yield 表达式置于 try 块内才能捕获 generator.throw() 注入的错误,因为 throw() 会使错误在 yield 所在行“冒泡”,若 yield 在 try 外则生成器直接终止。

不能直接用 try-catch 包裹 yield 语句来捕获外部注入的错误(比如调用 generator.throw()),因为 yield 本身不是抛出错误的源头,而是暂停点;真正触发错误的是外部对生成器的 throw() 调用,它会把错误“注入”到生成器内部当前暂停位置,并在该位置继续执行——此时错误是在 yield 表达式所在行“冒泡”出来的,所以 try-catch 必须包围整个 yield 所在的表达式或语句块。
错误必须被 yield 所在的 try 块捕获
Generator 函数中,generator.throw(err) 会让执行流跳回最近一个未完成的 yield 处,并把 err 当作该 yield 表达式的“异常返回值”。因此,要捕获它,yield 必须处于 try 块内,且 catch 在同一作用域中:
-
yield本身不抛错,但它是错误注入的“入口点” -
throw()调用后,控制权回到生成器,执行从yield后继续,此时若该yield在try内,错误就会进入catch - 如果
yield在try外,错误会直接向上冒泡,导致生成器终止(状态变为"completed")
正确写法示例
以下是一个可捕获外部 throw() 的典型结构:
function* myGen() {
try {
const res = yield 'ready'; // 错误会在这一行“出现”
console.log('res:', res); // 正常情况下才执行
} catch (e) {
console.error('caught:', e.message); // ✅ 捕获 generator.throw() 注入的错误
yield 'error handled';
}
}
<p>const g = myGen();
console.log(g.next()); // { value: 'ready', done: false }
console.log(g.throw(new Error('boom'))); // caught: boom → { value: 'error handled', done: false }
</p>
注意 yield 表达式的位置和上下文
常见易错点:
-
yield单独一行(如yield 1;)没有返回值参与计算,此时throw()仍会中断执行并进入catch,但不会影响“左侧变量”(因无赋值) - 若写成
const x = yield 1 + riskyCall();,则riskyCall()在yield求值时同步执行,其抛错属于普通 JS 错误,可被同级try-catch捕获;而generator.throw()是另一条错误路径,同样走这个catch -
finally块会在throw()或return()时执行,适合清理,但不能阻止错误传播(除非再 throw 或 return)
配合 next() 传值时的错误处理逻辑
外部可通过 next(value) 向 yield 表达式“返回值”,也可通过 throw(err) 向其“注入错误”。两者都发生在同一个暂停点,因此共享同一套 try-catch:
-
g.next(42)→yield表达式求值得到42,继续执行 -
g.throw(new Error())→yield表达式“抛出”该错误,触发catch - 二者互斥:一次暂停只能响应一个操作(next/throw/return)
不复杂但容易忽略:关键不是“包裹 yield 关键字”,而是确保 yield 所在的执行上下文处于 try 块保护范围内。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











