目录
基本概念
什么是 Generator 函数?
Generator 函数是 ES6 提供的一种异步编程解决方案,它可以让函数执行过程中被暂停和恢复。Generator 函数通过 function*
声明,内部使用 yield
关键字暂停执行。
特点
- 函数体内部使用 yield 表达式
- 函数返回一个遍历器对象
- 可以暂停执行和恢复执行
- 可以记住上一次运行状态
语法特性
1. 基本语法
javascript
function* generator() {
yield 1;
yield 2;
yield 3;
}
const gen = generator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
2. yield* 表达式
javascript
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
yield* foo(); // 委托给其他 Generator 函数
yield 'y';
}
const gen = bar();
console.log([...gen]); // ['x', 'a', 'b', 'y']
3. 传值与返回值
javascript
function* dataFlow() {
const x = yield 1;
const y = yield (x + 1);
return x + y;
}
const gen = dataFlow();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next(2)); // { value: 3, done: false }
console.log(gen.next(3)); // { value: 5, done: true }
使用场景
1. 异步操作流程控制
javascript
function* loadData() {
try {
const users = yield fetchUsers();
const posts = yield fetchPosts(users[0].id);
const comments = yield fetchComments(posts[0].id);
return { users, posts, comments };
} catch (error) {
console.error('Error:', error);
}
}
// 执行器函数
function run(generator) {
const gen = generator();
function next(data) {
const result = gen.next(data);
if (result.done) return result.value;
result.value.then(data => next(data));
}
return next();
}
run(loadData);
2. 迭代器实现
javascript
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
const numbers = range(1, 5);
for (const num of numbers) {
console.log(num); // 1, 2, 3, 4, 5
}
3. 状态机
javascript
function* trafficLight() {
while (true) {
yield 'red';
yield 'green';
yield 'yellow';
}
}
const light = trafficLight();
console.log(light.next().value); // 'red'
console.log(light.next().value); // 'green'
console.log(light.next().value); // 'yellow'
异步应用
1. 异步任务队列
javascript
function* taskQueue() {
const results = [];
try {
results.push(yield task1());
results.push(yield task2());
results.push(yield task3());
return results;
} catch (error) {
console.error('Task failed:', error);
}
}
2. 异步数据处理
javascript
function* processData(data) {
for (const item of data) {
const processed = yield transform(item);
yield save(processed);
}
}
高级用法
1. 双向通信
javascript
function* chat() {
while (true) {
const question = yield;
if (question === 'bye') break;
yield `Answer to: ${question}`;
}
}
const conversation = chat();
conversation.next(); // 启动生成器
console.log(conversation.next('How are you?').value); // "Answer to: How are you?"
2. 错误处理
javascript
function* errorHandler() {
try {
const a = yield operation1();
const b = yield operation2();
const c = yield operation3();
} catch (error) {
yield `Error occurred: ${error.message}`;
}
}
最佳实践
1. 使用执行器函数
javascript
function run(gen) {
const it = gen();
return new Promise((resolve, reject) => {
function next(data) {
const { value, done } = it.next(data);
if (done) return resolve(value);
Promise.resolve(value)
.then(data => next(data))
.catch(reject);
}
next();
});
}
2. 合理使用 yield*
javascript
function* combined() {
yield* generator1();
yield* generator2();
yield* generator3();
}
总结
-
Generator 优势:
- 控制函数执行流程
- 异步操作同步化表达
- 状态管理
- 迭代器实现
-
使用场景:
- 异步操作控制
- 数据流处理
- 状态机实现
- 迭代器生成
-
注意事项:
- 合理使用执行器
- 错误处理
- 避免过度使用
- 考虑可读性