Generator 本身不直接处理 Promise 终结,但可通过 runner 函数在 Promise resolve/reject 后调用 next() 或 throw() 将结果送回 yield 处,模拟 async/await;手写 runner 需递归驱动、正确传递值与错误;实际开发应优先使用原生 async/await。

Generator 本身不直接处理 Promise 的终结(即 then 或 catch),但它可以通过 手动控制执行流 + 外部驱动器(如 runner 函数),把 Promise 的 resolve/reject 结果“送回” Generator 内部,从而在 yield 表达式处继续执行并拿到结果——这本质上是模拟 async/await 的行为。
Generator 配合 Promise 的核心机制
Generator 函数返回一个迭代器,每次调用 next() 会暂停在 yield 处;而 Promise 的 then 是异步回调。要把两者串起来,关键在于:
- 用
yield暂停,并把 Promise 对象交出去 - 在 Promise 成功/失败后,调用
iterator.next(value)或iterator.throw(error)把结果“推回去” - 需要一个递归或循环的 runner 来持续驱动这个过程
手写一个简易 Runner(支持 Promise 终结)
下面是一个能自动处理 Promise 并正确传递 resolve 值和 reject 错误的 runner:
function run(genFn) {
const gen = genFn();
<p>function next(data) {
const result = gen.next(data);
if (result.done) return result.value;</p><pre class="brush:php;toolbar:false;">const value = result.value;
if (value instanceof Promise) {
value.then(
res => next(res),
err => gen.throw(err)
);
} else {
next(value);
}}
next(); }
使用示例:
function* fetchUser() {
try {
const res = yield fetch('/api/user');
const user = yield res.json(); // 注意:res.json() 也返回 Promise
console.log('User:', user);
} catch (err) {
console.error('Fetch failed:', err);
}
}
<p>run(fetchUser); // 自动执行,支持 Promise then/catch</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6235" title="Java Maven Code Review"><img
src="https://img.php.cn/upload/skill/000/000/081/179084711841712.jpg" alt="Java Maven Code Review" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill6235" title="Java Maven Code Review" class="overflowclass">Java Maven Code Review</a>
<p class="overflowclass">审查Java Maven项目(ZIP压缩包或GitLab仓库URL),检查代码规范、命名、模块边界、可维护性问题以及重复代码。</p>
</div>
<a rel="nofollow" href="/xiazai/skill6235" title="Java Maven Code Review" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
这里 yield fetch(...) 暂停,runner 拿到 Promise 后,在 then 中调用 next(res),值就出现在 const res = yield ... 左侧;出错时用 gen.throw(err),会被 try/catch 捕获。
注意终结回调的时机与错误传播
Promise 的 then(onFulfilled, onRejected) 中的 onRejected 并不等价于 catch —— 它只捕获前一个 Promise 的 rejection,且不会中断链。在 Generator 中,你更应依赖 gen.throw() 将错误注入,让语法层面的 try/catch 生效:
- 不要在
yield后直接写.catch(),那会吞掉错误,导致gen.throw不被触发 - 如果某个 Promise 必须自行处理错误(如降级逻辑),应在它内部
catch并返回一个“安全值”,避免 throw 到 runner 外 - runner 中的
gen.throw(err)必须对应 Generator 内有try/catch或未捕获时终止迭代器
现代替代方案:优先用 async/await
Generator + Runner 是 async/await 的底层思想原型,但实际项目中已极少手写。除非你在实现协程库、状态机、或需深度定制暂停/恢复逻辑(如 Redux-Saga),否则直接用 async function 更清晰可靠:
async function fetchUser() {
try {
const res = await fetch('/api/user');
const user = await res.json();
console.log('User:', user);
} catch (err) {
console.error('Fetch failed:', err);
}
}
它天然支持 Promise 终结,语法简洁,调试友好,V8 优化成熟。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










