Generator函数通过function*定义,使用yield暂停执行并返回遍历器对象;每次调用next()恢复执行,实现可中断的异步流程控制。

Generator 函数是 JavaScript 中一种特殊的函数类型,它允许你在函数执行过程中暂停和恢复。这种能力使得 Generator 在处理异步流程、迭代器构建以及状态管理等方面非常有用。要理解其原理,需要从语法特性、内部机制与底层实现三个层面来看。
1. 语法特征与基本用法
Generator 函数通过 function* 定义,并使用 yield 关键字来暂停执行:
function* gen() {console.log("A");
yield 1;
console.log("B");
yield 2;
return "done";
}
const g = gen();
g.next(); // 输出 A,返回 { value: 1, done: false }
g.next(); // 输出 B,返回 { value: 2, done: false }
g.next(); // 返回 { value: "done", done: true }
调用 Generator 函数并不会立即执行函数体,而是返回一个 遍历器对象(Iterator)。只有当调用该对象的 next() 方法时,函数才会开始或继续执行,直到遇到下一个 yield 或 return。
2. 执行上下文的暂停与恢复机制
普通函数一旦开始执行,就会一直运行到结束(或抛出异常),而 Generator 的核心在于它可以保存当前执行状态并在之后恢复。
立即学习“Java免费学习笔记(深入)”;
这背后依赖于 V8 引擎对执行栈(call stack)和上下文(execution context)的管理方式:
- 每次遇到 yield,函数会将当前的执行位置、局部变量等状态保留下来
- 控制权交还给调用者,函数进入“暂停”状态
- 下一次调用 next() 时,引擎恢复之前保存的上下文,从 yield 后继续执行
这种行为类似于协程(coroutine),即用户态的轻量级线程,可以在多个断点之间切换执行流。
3. 状态机的本质实现
从编译角度看,Generator 函数在底层被转换为一个基于状态机的状态对象。
Babel 或 TypeScript 编译器在没有原生支持的情况下,会将 Generator 转换为一个包含 switch-case 的状态机结构。例如:
function* gen() {yield 1;
yield 2;
}
// 可被转化为类似:
function gen() {
let state = 0;
return {
next() {
switch (state) {
case 0:
state = 1;
return { value: 1, done: false };
case 1:
state = 2;
return { value: 2, done: false };
default:
return { value: undefined, done: true };
}
}
};
}
每个 yield 对应一个状态分支,通过 state 变量追踪当前执行进度。这种方式让函数具备了“可中断”的能力,而无需依赖操作系统的线程调度。
4. yield 与 next 的双向通信
Generator 不只是单向产出值,还可以接收外部输入:
function* gen() {const a = yield "hello";
console.log(a); // 接收 next 传入的值
}
const g = gen();
g.next(); // { value: "hello", done: false }
g.next("world"); // 输出 "world",{ value: undefined, done: true }
第一次 next() 启动函数并停在第一个 yield;第二次 next("world") 不仅恢复执行,还将参数赋值给 yield 表达式的返回结果。这说明 yield 是一个表达式,可以有返回值。
这种双向通信机制是实现复杂控制逻辑的基础,比如用于构建异步流程控制器(如早期的 co 库)。
5. 与 Promise 结合实现异步流程控制
虽然现在普遍使用 async/await,但在 Promise 刚流行时,Generator 常被用来模拟同步写法:
function fetchUser() {return fetch('/api/user').then(res => res.json());
}
function* main() {
try {
const user = yield fetchUser();
console.log(user);
} catch (err) {
console.error(err);
}
}
配合一个 runner 函数(如 co),可以自动执行 Generator 并处理 Promise 的 resolve/reject,从而实现“以同步形式书写异步逻辑”。
async 函数本质上就是 Generator + Promise + 自动执行器的语法糖。
基本上就这些。Generator 的本质是一个可暂停、可恢复、支持双向通信的函数,其实现依赖于状态机模型和执行上下文的保存与恢复。尽管现代开发中更多使用 async/await,但理解 Generator 有助于深入掌握 JavaScript 的异步机制和迭代协议设计思想。










