JavaScript迭代器_生成器异步应用

迭代器与生成器可通过yield暂停执行,结合Promise实现异步控制。示例中,生成器函数yield出Promise,由外部处理并回传结果,从而实现清晰的异步流程。通过自定义run函数可自动执行该过程,原理类似co库,虽async/await已成主流,但生成器在复杂控制流与任务调度中仍有价值,有助于理解异步机制演化与底层逻辑。

JavaScript中的迭代器和生成器不只是用来处理数据序列的工具,它们在异步编程中也有强大应用。通过结合yieldPromise,我们可以写出更清晰、可控的异步逻辑。

迭代器与生成器基础回顾

迭代器是一个对象,包含一个next()方法,返回{ value, done }结构。生成器函数用function*定义,调用后返回一个迭代器。

生成器的特点是能通过yield暂停执行,直到下一次next()被调用。

示例:

function* simpleGen() {
  yield 1;
  yield 2;
  return 3;
}
const it = simpleGen();
it.next(); // { value: 1, done: false }
it.next(); // { value: 2, done: false }
it.next(); // { value: 3, done: true }

生成器实现异步控制

虽然现在普遍使用async/await,但在早期,生成器常用于模拟异步流程。原理是:生成器yield一个Promise,外部迭代器获取该Promise并等待其完成,再将结果送回生成器继续执行。

这种模式被称为“yielding promises”。

手动执行示例:

function* asyncGen() {
  const data = yield fetch('/api/data');
  console.log(data);
}

const it = asyncGen(); const promise = it.next().value; // 获取fetch Promise promise.then(res => res.json()) .then(data => it.next(data)); // 将结果送回

自动运行异步生成器(自定义runner)

可以封装一个通用函数来自动处理生成器中的Promise,类似co库的原理。

实现一个简单的run函数:

function run(genFunc) {
  const gen = genFunc();

function next(val) { const result = gen.next(val); if (result.done) return Promise.resolve(result.value);

return Promise.resolve(result.value)
  .then(data => next(data));

}

return next(); }

使用方式:

run(function* () {
  const resp = yield fetch('/user');
  const user = yield resp.json();
  const postsResp = yield fetch(`/posts?uid=${user.id}`);
  const posts = yield postsResp.json();
  console.log(posts);
});

实际应用场景与意义

尽管async/await已成主流,理解生成器在异步中的应用仍有价值。

  • 学习JavaScript异步演化过程,有助于深入理解async/await底层机制
  • 在需要复杂控制流(如暂停、恢复、注入值)时,生成器仍具优势
  • 某些状态机、任务调度场景中,生成器可提供更直观的编码方式

基本上就这些。生成器曾是异步编程的重要桥梁,如今虽被async/await取代,但其思想仍在框架和工具中留有痕迹。掌握它,能让你更好地理解现代JS的运作逻辑。