定义Generator
想象我们有一台 自助提款机(ATM)
- 普通函数 → 一次性取完所有钱(一口气执行完)
- Generator 函数 → 按需分次取钱(每次取一笔,暂停等待下次指令)
// 定义 Generator 函数(带 * 号)
function* atmMachine() {
yield "取出100元"; // 第一次暂停点
yield "取出200元"; // 第二次暂停点
return "余额为0"; // 结束
}
// 启动 ATM(不立即执行)
const atm = atmMachine();
核心机制:分段执行
通过 next() 控制执行流程
console.log(atm.next()); // { value: "取出100元", done: false }
console.log(atm.next()); // { value: "取出200元", done: false }
console.log(atm.next()); // { value: "余额为0", done: true }(结束)
yield:暂停执行并返回当前值(类似 ATM 吐钞)next():继续执行到下一个yield或return- 返回值:每次返回
{ value: 值, done: 是否结束 }
核心特性
双向通信:next() 可传入参数
传入的参数会作为上一个 yield 的返回值
function* chatBot() {
const name = yield "你的名字?"; // 暂停等待输入
yield `你好,${name}!`;
}
const bot = chatBot();
bot.next(); // 启动,返回 { value: "你的名字?", done: false }
bot.next(" 小明"); // 传入"小明",返回 { value: "你好,小明!", done: false }
应用:动态调整函数行为
提前终止:return() 强制结束
console.log(atm.next()); // 取100元
console.log(atm.return(" 故障终止")); // { value: "故障终止", done: true }(直接结束)
错误处理:throw() 注入异常
在暂停处抛出错误
function* task() {
try {
yield "步骤1";
} catch (e) {
yield `错误:${e}`;
}
}
const t = task();
t.next(); // { value: "步骤1", done: false }
t.throw(" 网络断开"); // { value: "错误:网络断开", done: false }
与迭代器无缝协作
Generator 函数返回的对象自带迭代器接口,可直接用 for...of 遍历
function* countTo3() {
yield 1;
yield 2;
yield 3;
}
for (const num of countTo3()) {
console.log(num); // 依次输出 1, 2, 3
}
一些常见的使用场景
解决回调地狱(异步流程控制)
用同步写法处理异步操作(需配合 Promise)
function* fetchUser() {
const user = yield fetch("/user"); // 暂停等待请求
const posts = yield fetch(`/posts?user=$`);
return posts;
}
// 需用执行器自动调度(如 co 库)
runGenerator(fetchUser);
按需生成数据流
适合大数据分页加载
function* loadPages() {
let page = 1;
while (true) {
const data = yield fetch(`/data?page=$`);
if (!data.length) break;
page++;
}
}
自定义迭代逻辑
简化迭代器实现(如遍历树结构)
function* traverseTree(node) {
yield node.value;
for (const child of node.children) {
yield* traverseTree(child); // 递归嵌套
}
}
yield* 可委托执行另一个 Generator
Generator vs Async/Await
| 特性 | Generator | Async/Await |
|---|---|---|
| 语法 | function* + yield | async + await |
| 执行器依赖 | 需外部调度器(如 co) | 原生支持 |
| 异步方案 | 过渡方案(ES6) | 终极方案(ES2017) |
| 适用场景 | 复杂状态机、自定义迭代 | 主流异步编程 |
牢记
Generator 是 “可暂停的函数” ,通过 yield 分段返回数据,用 next() 控制进度,适合解决复杂状态流转和异步流程控制问题