es6的Generator函数用法

目录

  1. 基本概念
  2. 语法特性
  3. 使用场景
  4. 异步应用
  5. 高级用法
  6. 最佳实践

基本概念

什么是 Generator 函数?

Generator 函数是 ES6 提供的一种异步编程解决方案,它可以让函数执行过程中被暂停和恢复。Generator 函数通过 function* 声明,内部使用 yield 关键字暂停执行。

特点

  1. 函数体内部使用 yield 表达式
  2. 函数返回一个遍历器对象
  3. 可以暂停执行和恢复执行
  4. 可以记住上一次运行状态

语法特性

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();
}

总结

  1. Generator 优势:

    • 控制函数执行流程
    • 异步操作同步化表达
    • 状态管理
    • 迭代器实现
  2. 使用场景:

    • 异步操作控制
    • 数据流处理
    • 状态机实现
    • 迭代器生成
  3. 注意事项:

    • 合理使用执行器
    • 错误处理
    • 避免过度使用
    • 考虑可读性
相关推荐
mldong7 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi11 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu12 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss