yield 是协程式暂停点,不挂起状态而由生成器对象自动维护上下文;它中止执行并返回值,next() 调用时从下一行恢复,局部变量、执行位置等全由引擎隐式保存。

yield 本身不“挂起状态”,它只是中止生成器函数的执行,并把控制权交还给调用方,同时返回一个值;真正的“状态常驻”由生成器对象(Generator Object)内部自动维护——你无需手动保存变量或上下文。
理解 yield 的本质:协程式暂停点,而非线程挂起
yield 不是让 JavaScript 引擎冻结整个执行栈,而是告诉生成器:“停在这儿,把右边的表达式结果交给 next() 调用者,等下次再进来时,从下一行继续”。生成器函数的局部变量、执行位置、try/catch 状态全部保留在内存中,由引擎隐式管理。
- 每次调用 next(),生成器才从上次 yield 处恢复,不是自动循环或定时唤醒
- yield 只能在 generator function(用 function* 声明)中使用,普通函数里会报语法错误
- yield 表达式本身有返回值:它接收 next() 传入的参数作为本次 yield 的“返回值”(即上一轮 yield 的返回值)
用 yield 实现可中断、可恢复的异步流程
配合 Promise + 封装的 runner(如 co 或手写 async/await 兼容层),yield 可以让异步操作看起来像同步代码,且每一步都可精确暂停和恢复。
- 写法示例:function* fetchFlow() { const user = yield fetch('/user'); yield console.log(user.name); }
- 关键点:fetch 返回 Promise,但 yield 不会自动 await 它;需要 runner 函数识别 Promise 并在 resolve 后自动调用 next(value)
- 错误处理需用 try/catch 包裹 yield 行,因为 throw() 会把异常注入到当前暂停点
避免常见误区:状态不是 yield 给的,是生成器对象持有的
很多人误以为 yield “保存了状态”,其实真正持久化执行上下文的是生成器实例(如 const gen = myGen())。只要这个对象没被 GC,它的内部状态就一直存在。
- 重复调用同一个生成器函数(myGen())会创建新实例,彼此状态完全隔离
- yield 后未调用 next(),生成器就永远停在那,变量不会丢失,也不会触发 GC
- 不能在 yield 后直接访问外部闭包变量来“模拟状态”——那不是 yield 的功劳,是 JS 作用域本就如此
实际场景建议:优先用 async/await,仅在需多阶段手动控制时用 yield
现代开发中,async/await 已覆盖绝大多数异步控制流需求。yield + Generator 更适合需要精细干预执行节奏的场景:
- 实现自定义迭代协议(比如分页拉取并逐条 yield 数据)
- 构建状态机:每个 yield 对应一个状态,next() 触发状态迁移
- 调试用暂停器:在 yield 处打断点,观察中间值,再手动 next() 推进
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











