JavaScript Generator 函数详解:从基础到高级应用

JavaScript Generator 函数详解:从基础到高级应用

Generator 是 JavaScript 中一种特殊的函数,它可以通过 yield 关键字暂停和恢复执行,为异步编程、惰性求值和迭代器模式提供了强大的支持。


1. Generator 基础

1.1 基本语法

Generator 函数通过 function* 声明,内部使用 yield 暂停执行,并通过 .next() 恢复执行。

function* simpleGenerator() {
  yield 'First value';
  yield 'Second value';
  return 'Done';
}

const gen = simpleGenerator();

console.log(gen.next()); // { value: 'First value', done: false }
console.log(gen.next()); // { value: 'Second value', done: false }
console.log(gen.next()); // { value: 'Done', done: true }

1.2 yieldnext() 的交互

  • yield:暂停函数执行,并返回右侧的值。
  • .next():恢复执行,可以传入参数作为 yield 的返回值。
function* genWithInput() {
  const a = yield 'First yield';
  const b = yield a + ' Second yield';
  return b;
}

const gen = genWithInput();

console.log(gen.next());       // { value: 'First yield', done: false }
console.log(gen.next('Hello')); // { value: 'Hello Second yield', done: false }
console.log(gen.next('End'));  // { value: 'End', done: true }

2. Generator 高级用法

2.1 生成无限序列

Generator 可以惰性计算,适合生成无限数据流。

function* infiniteNumbers() {
  let n = 0;
  while (true) {
    yield n++;
  }
}

const numbers = infiniteNumbers();
console.log(numbers.next().value); // 0
console.log(numbers.next().value); // 1
// ...可以无限调用

2.2 实现自定义迭代器

Generator 函数天然支持 Symbol.iterator,可以用于自定义迭代逻辑。

const myIterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};

for (const num of myIterable) {
  console.log(num); // 1, 2, 3
}

2.3 异步 Generator(for-await-of

结合 asyncyield,可以处理异步数据流。

async function* asyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}

(async () => {
  for await (const num of asyncGenerator()) {
    console.log(num); // 1, 2, 3
  }
})();

3. Generator 与协程(Coroutine)

Generator 可以模拟协程(Coroutine),实现更复杂的控制流。

3.1 协程调度示例

function* taskA() {
  console.log('Task A - Step 1');
  yield;
  console.log('Task A - Step 2');
}

function* taskB() {
  console.log('Task B - Step 1');
  yield;
  console.log('Task B - Step 2');
}

const a = taskA();
const b = taskB();

a.next(); // "Task A - Step 1"
b.next(); // "Task B - Step 1"
a.next(); // "Task A - Step 2"
b.next(); // "Task B - Step 2"

3.2 结合 co 库实现自动执行

// 模拟 co 库(自动执行 Generator)
function co(generator) {
  const gen = generator();
  function handle(result) {
    if (result.done) return Promise.resolve(result.value);
    return Promise.resolve(result.value)
      .then((res) => handle(gen.next(res)))
      .catch((err) => handle(gen.throw(err)));
  }
  return handle(gen.next());
}

co(function* () {
  const data1 = yield Promise.resolve(1);
  const data2 = yield Promise.resolve(2);
  console.log(data1 + data2); // 3
});

4. Generator 实战应用

4.1 实现 Redux-Saga 风格的异步流

function* userSaga() {
  try {
    const user = yield call(fetchUser);
    yield put({ type: 'USER_LOADED', payload: user });
  } catch (error) {
    yield put({ type: 'USER_ERROR', error });
  }
}

4.2 实现分页数据流

async function* paginatedData(url) {
  let page = 1;
  while (true) {
    const response = await fetch(`${url}?page=${page}`);
    const data = await response.json();
    if (data.length === 0) break;
    yield data;
    page++;
  }
}

(async () => {
  for await (const items of paginatedData('/api/data')) {
    console.log(items);
  }
})();

5. Generator vs Async/Await

特性GeneratorAsync/Await
语法function* + yieldasync + await
返回值迭代器对象({value, done}Promise
适用场景复杂控制流、惰性计算简单异步代码
自动执行需要手动 .next()co自动执行
错误处理try/catch + .throw()try/catch

总结

  1. Generator 的核心function* + yield,可暂停和恢复执行。
  2. 主要用途
    • 惰性计算(无限序列)。
    • 自定义迭代器(Symbol.iterator)。
    • 异步控制流(结合 for-await-ofco)。
  3. 高级应用:协程、Redux-Saga、分页数据流。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王小玗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值