promise微任务+generator组合构建异步调度器,本质是利用generator暂停/恢复能力与promise微任务队列机制,手动模拟async/await的同步书写风格和确定性调度顺序,不依赖原生async支持。

Promise 微任务 + Generator 组合构建异步调度器,本质是用 Generator 暂停/恢复执行的能力,配合 Promise 的状态流转与微任务队列机制,手动模拟出类似 async/await 的同步书写风格和确定性调度顺序。它不依赖运行时原生 async 支持,适合理解底层、定制化控制或在低版本环境做轻量兼容。
Generator 提供“可中断的执行上下文”
Generator 函数通过 * 声明,内部用 yield 标记暂停点。每次调用 iterator.next(),函数从上次暂停处继续执行,直到下一个 yield 或结束。
-
yield后面可以是任意值,但若返回的是 Promise,就为后续“等它完成再继续”提供了接口 - Generator 自身不处理异步,它只是把控制权交还给外部执行器,并等待下一次
next(value)被调用——这个value就是上一个 Promise 的 resolve 结果 - 关键点:Generator 的执行栈帧被 JS 引擎挂起并保留在内存中(非销毁),所以变量作用域、执行位置都完整保留
Promise 微任务确保“时机可控”
Promise 的 resolve / reject 触发后,其 .then() 回调会被推入**微任务队列(microtask queue)**,在当前宏任务结束后、下一个宏任务开始前立即执行。
- 这保证了调度器能以“最小延迟、最高优先级”驱动 Generator 恢复,避免 setTimeout 等宏任务引入不可控延迟
- 所有
yield Promise后的恢复逻辑,都统一走微任务路径,形成稳定、可预测的执行节奏 - 例如:
yield fetch('/api')→ fetch 返回 Promise → Promise resolve → 微任务触发it.next(result)→ Generator 继续执行
调度器核心逻辑:自动执行器
一个典型的调度器就是一个递归调用的函数,接收 Generator Iterator,持续 next() 并处理返回值:
- 若
iterator.next().value是 Promise,则用.then(res => run(res))在微任务中传入结果并再次next - 若返回
{ done: true },流程结束;若中间 reject,需捕获并 throw 到 Generator 内(可用iterator.throw(err)) - 可扩展支持
yield* anotherGenerator、错误重试、超时包装、并发限制等策略
实际组合示例(精简版)
以下是一个可运行的调度器骨架:
function co(genFn) {
const gen = genFn();
function run(result) {
const { value, done } = gen.next(result);
if (done) return value;
if (value instanceof Promise) {
value.then(run).catch(err => gen.throw(err));
}
}
run();
}
<p>// 使用
co(function* () {
const user = yield new Promise(r => setTimeout(() => r({ id: 1 }), 100));
console.log('user:', user); // user: { id: 1 }
const posts = yield Promise.resolve([{ title: 'a' }]);
console.log('posts:', posts);
});</p>这段代码没有 async/await,却实现了清晰的线性异步流,且每一步都在微任务边界内完成交接。










