Generator函数不直接处理异步,仅提供可暂停/恢复的执行机制;需配合yield与运行器(如co)或async/await才能简化异步流程。
JavaScript 生成器(Generator)本身**不直接处理异步**,也不能自动“简化”异步流程;它只是提供了一种可暂停、可恢复的函数执行机制。真正简化异步的是配合 yield 和外部运行器(比如 co)或现代 async/await 的模式演进——而 async/await 正是基于生成器思想但更安全、更易用的替代方案。
Generator 函数?它是一个用 function* 声明、内部含 yield 表达式、返回 Iterator 对象的特殊函数。每次调用 next(),函数执行到下一个 yield 暂停,并把值交还给调用方。
function* countdown(n) {
while (n > 0) {
yield n;
n--;
}
}
const gen = countdown(3);
console.log(gen.next().value); // 3
console.log(gen.next().value); // 2
console.log(gen.next().value); // 1yield 不是 return:它暂停执行,保留当前上下文(变量、作用域、执行点)next()、throw()、return() 方法,可主动控制流程new 调用,也不绑定 this
Generator 写异步逻辑?在 Promise 普及但 async/await 尚未进入标准时(ES2015–ES2016),开发者借助 yield 把异步操作“看起来像同步”——前提是配合一个能识别 Promise 并自动 next() 的运行器(如 co 库)。
const co = require('co');
function* fetchUserData() {
const user = yield fetch('/api/user');
const data = yield user.json();
return data.name;
}
co(fetchUserData).then(name => console.log(name));
yield 后跟一个 Promise,co 会等它 resolve 后再调用 next(value)
try/catch 捕获,因为 co 在 reject 时调用 gen.throw(err)
Generator 在现代代码中还有必要手动用吗?绝大多数场景下**不需要**。ES2017 引入的 async/await 已覆盖其核心价值,且更健壮:
async 函数返回真正的 Promise,可直接 .then() 或 await,无需额外运行器debugger 单步可进 await 后的代码Generator 无法 await,也不能被 await 直接消费;必须包装成 Promise 才能接入现代异步生态真正容易被忽略的是:生成器的暂停能力只在同步上下文中“可靠”。一旦混入异步副作用(比如在
yield 后修改闭包变量),或忘记处理 throw() / return(),行为就会变得难以预测——这正是它被 async/await 取代的关键原因。