生成器函数通过function*和yield实现暂停恢复机制,可yield promise供外部runner驱动异步流程,但现代开发优先使用async/await。

ES6 的生成器函数(Generator Function)本身不直接处理异步,但它提供了一种可暂停、可恢复的执行机制,配合 yield 和迭代器协议,能优雅地组织异步逻辑。关键在于:把异步操作“交还控制权”,再由外部(如自定义 runner 或 Promise 驱动器)决定何时恢复。
生成器函数基础:用 function* 和 yield 暂停
生成器函数用 function* 声明,内部用 yield 暂停执行,并返回一个迭代器对象。每次调用 next(),函数从上次暂停处继续,直到下一个 yield 或结束。
例如:
function* countdown(n) {
while (n > 0) {
yield n;
n--;
}
return "done";
}
<p>const it = countdown(3);
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: "done", done: true }
</p>这说明生成器天然支持分步执行——这是控制异步流的基石。
用生成器封装异步操作:yield 返回 Promise
生成器不运行异步代码,但可以 yield 一个 Promise,把“下一步该等谁”暴露给外部调度器。比如:
function* fetchUserFlow() {
const userRes = yield fetch('/api/user');
const userData = yield userRes.json();
const postsRes = yield fetch(`/api/posts?userId=${userData.id}`);
const posts = yield postsRes.json();
return { user: userData, posts };
}
注意:上面代码不会自动执行;yield 后的 fetch 被立即调用并返回 Promise,但后续 .json() 等链式操作需在恢复时手动处理。
要点:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
yield表达式本身不等待 Promise,它只是暂停并传出 Promise 对象 - 真正等待和恢复,必须靠外部 runner 来
await并调用next(value) - 推荐
yield原始 Promise(如fetch(...)),而非已await的值
手写简易 Runner:自动处理 Promise 并恢复生成器
一个轻量 runner 可递归驱动生成器,遇到 Promise 就 await,再把结果传回 next():
function run(genFn, ...args) {
const gen = genFn(...args);
<p>function next(data) {
const { value, done } = gen.next(data);
if (done) return Promise.resolve(value);
return Promise.resolve(value).then(next);
}</p><p>return next();
}</p><p>// 使用
run(fetchUserFlow).then(result => console.log(result));
</p>这个 run 函数会:
- 调用
gen.next()获取第一个yield值(通常是 Promise) - 用
Promise.resolve(value).then(next)确保无论value是不是 Promise 都能处理 - 当 Promise resolve 后,把结果作为
data传入下一次next(data),即恢复生成器
这样就实现了“写起来像同步,执行是异步”的效果。
现代替代方案:async/await 已覆盖大部分场景
虽然生成器 + runner 能实现协程式异步流,但 ES2017 引入的 async/await 更简洁、原生支持、调试友好:
async function fetchUserFlow() {
const userRes = await fetch('/api/user');
const userData = await userRes.json();
const postsRes = await fetch(`/api/posts?userId=${userData.id}`);
const posts = await postsRes.json();
return { user: userData, posts };
}
除非你在做框架开发(如早期 co 库)、需要精细控制执行时机(如游戏帧循环、状态机),或兼容极老环境,否则优先使用 async/await。
生成器的价值更多体现在:迭代器协议、惰性求值、状态机建模、与 for...of / Array.from 配合等非异步场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










