generator基础知识
Generator 是 ES6 中新增的语法,和 Promise 一样,都可以用来异步编程。Generator 函数可以说是 Iterator 接口的具体实现方式。Generator 最大的特点就是可以控制函数的执行。
- function* 用来声明一个函数是生成器函数,它比普通的函数声明多了一个
*
,\*
的位置比较随意可以挨着 function 关键字,也可以挨着函数名 - yield 产出的意思,这个关键字只能出现在生成器函数体内,但是生成器中也可以没有 yield 关键字,函数遇到 yield 的时候会暂停,并把 yield 后面的表达式结果抛出去
- next 作用是将代码的控制权交还给生成器函数
function* foo(x) {
let y = 2 * (yield x + 1);
let z = yield y / 3;
return x + y + z;
}
let it = foo(5);
console.log(it.next()); // => {value: 6, done: false}
console.log(it.next(12)); // => {value: 8, done: false}
console.log(it.next(13)); // => {value: 42, done: true}
上面这个示例就是一个 Generator 函数,来分析其执行过程:
- 首先 Generator 函数调用时它会返回一个迭代器
- 当执行第一次 next 时,传参会被忽略,并且函数暂停在
yield (x + 1)
处,所以返回5 + 1 = 6
- 当执行第二次 next 时,传入的参数等于上一个 yield 的返回值,如果不传参,yield 永远返回 undefined。此时
let y = 2 * 12
,所以第二个 yield 等于2 * 12 / 3 = 8
- 当执行第三次 next 时,传入的参数会传递给 z,所以
z = 13
,x = 5
,y = 24
,相加等于 42
yield 实际就是暂缓执行的标示,每执行一次 next(),相当于指针移动到下一个 yield 位置
总结一下,Generator 函数是 ES6 提供的一种异步编程解决方案。通过 yield 标识位和 next()方法调用,实现函数的分段执行
遍历器对象生成函数,最大的特点是可以交出函数的执行权
- function 关键字与函数名之间有一个星号;
- 函数体内部使用 yield 表达式,定义不同的内部状态;
- next 指针移向下一个状态
这里可以说说 Generator 的异步编程,以及它的语法糖 async 和 awiat,传统的异步编程。ES6 之前,异步编程大致如下
- 回调函数
- 事件监听
- 发布/订阅
传统异步编程方案之一:协程,多个线程互相协作,完成异步任务。
// 使用 * 表示这是一个 Generator 函数
// 内部可以通过 yield 暂停代码
// 通过调用 next 恢复执行
function* test() {
let a = 1 + 2;
yield 2;
yield 3;
}
let b = test();
console.log(b.next()); // > { value: 2, done: false }
console.log(b.next()); // > { value: 3, done: false }
console.log(b.next()); // > { value: undefined, done: true }
从以上代码可以发现,加上 *
的函数执行后拥有了 next 函数,也就是说函数执行后返回了一个对象。每次调用 next 函数可以继续执行被暂停的代码。以下是 Generator 函数的简单实现
// cb 也就是编译过的 test 函数
function generator(cb) {
return (function () {
var object = {
next: 0,
stop: function () {},
};
return {
next: function () {
var ret = cb(object);
if (ret === undefined) return { value: undefined, done: true };
return {
value: ret,
done: false,
};
},
};
})();
}
// 如果使用 babel 编译后可以发现 test 函数变成了这样
function test() {
var a;
return generator(function (_context) {
while (1) {
switch ((_context.prev = _context.next)) {
// 可以发现通过 yield 将代码分割成几块
// 每次执行 next 函数就执行一块代码
// 并且表明下次需要执行哪块代码
case 0:
a = 1 + 2;
_context.next = 4;
return 2;
case 4:
_context.next = 6;
return 3;
// 执行完毕
case 6:
case "end":
return _context.stop();
}
}
});
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南