极简三分钟ES6 - Generator生成器

59 阅读2分钟

定义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

特性GeneratorAsync/Await
语法function* + yieldasync + await
执行器依赖需外部调度器(如 co原生支持
异步方案过渡方案(ES6)终极方案(ES2017)
适用场景复杂状态机、自定义迭代主流异步编程

牢记

Generator 是  “可暂停的函数” ,通过 yield 分段返回数据,用 next() 控制进度,适合解决复杂状态流转和异步流程控制问题