验证yield异步流程需确认“暂停→等待Promise完成→恢复执行并传入结果”链路:手动驱动next()、观察console/debugger日志、用co封装断言、校验时序与双向通信。

测试生成器函数中 yield 的异步流程,核心是验证“暂停 → 等待 Promise 完成 → 恢复执行并传入结果”这一链路是否按预期工作。不能只看 yield 是否暂停,更要确认 next() 是否在 Promise resolve 后被正确调用,且返回值是否准确注入到 yield 表达式左侧。
手动驱动 + 断点/日志观察
这是最直接、适合调试的方式:不依赖库,自己控制 next() 时机,配合 console 或 debugger 查看每一步状态。
- 定义一个带异步操作的生成器,比如
yield new Promise(resolve => setTimeout(() => resolve('done'), 100)) - 调用生成器得到迭代器,立即调用
next(),记录返回对象({ value: Promise, done: false }) - 对
value(即 Promise)调用.then(res => it.next(res)),并在then回调里加console.log('res:', res)和后续next()的输出 - 在 yield 行前后加
console.log('before yield')和console.log('after yield, got:', value),确认执行顺序
用 co 或自定义 runner 封装后断言
co 库会自动处理 Promise、数组、对象等 yield 值,并统一抛错。测试重点转为验证最终结果和错误路径。
- 安装 co:
npm install co(或使用 ESM 导入) - 写一个生成器,例如
function* testGen() { return yield Promise.resolve(42); } - 用
co(testGen).then(res => expect(res).toBe(42))测试成功路径 - 用
co(function* () { yield Promise.reject(new Error('boom')) }).catch(err => expect(err.message).toBe('boom'))测试失败路径 - 注意:co 返回的是 Promise,所有断言需在 then/catch 中进行
模拟异步副作用并校验执行时序
yield 的异步流程是否生效,关键看副作用(如 API 调用、文件读取)是否真被“等待”,而非并发执行。
- 创建两个 mock 异步函数,都返回 Promise,但延迟不同(如 200ms 和 50ms)
- 在生成器中按顺序
yield first(); yield second(); - 用
Date.now()或计数器记录每个函数 resolve 时间点 - 断言:second 的 resolve 时间必须晚于 first 的 resolve 时间(证明 second 确实等 first 完成后才发起)
- 对比直接 Promise.all 或串行 .then 的行为,确认生成器版本是严格串行、阻塞式等待
检查 yield 表达式的双向通信是否正常
yield 不仅向外输出值,还接收 next(value) 传入的数据。异步场景下,常需把 resolve 结果传回给 yield 左侧变量。
- 写生成器:
function* gen() { const a = yield Promise.resolve(100); console.log(a); return a * 2; } - 手动驱动:先
it.next()得到 Promise,再.then(x => it.next(x)) - 断言:控制台应输出
100,且最终it.next().value是200 - 若改用
it.next(999)替代.then(x => it.next(x)),则输出应为999—— 可借此验证传参机制未被异步逻辑干扰


















