9.4 异步生成器与 for await...of

9.4 异步生成器与 for await...of

异步生成器(Async Generator)是 ES2018 引入的特性,结合了生成器函数和异步操作的能力。通过 for await...of 循环,可以方便地遍历异步生成器产生的值。本节将详细介绍异步生成器的用法及其应用场景。


9.4.1 异步生成器的基本概念

异步生成器使用 async function* 定义,内部通过 yield 产生值。与普通生成器不同,异步生成器产生的值可以是 Promise

1. 定义异步生成器

async function* asyncGenerator() {
  yield "First";
  yield "Second";
  yield "Third";
}

2. 异步生成器对象
异步生成器返回的生成器对象是一个异步迭代器,可以通过 next() 方法获取值:

const generator = asyncGenerator();

generator.next().then((result) => {
  console.log(result); // 输出 { value: "First", done: false }
});

generator.next().then((result) => {
  console.log(result); // 输出 { value: "Second", done: false }
});

generator.next().then((result) => {
  console.log(result); // 输出 { value: "Third", done: false }
});

generator.next().then((result) => {
  console.log(result); // 输出 { value: undefined, done: true }
});

9.4.2 for await...of 循环

for await...of 是 ES2018 引入的语法,用于遍历异步迭代器(如异步生成器)。

1. 基本用法

async function* asyncGenerator() {
  yield "First";
  yield "Second";
  yield "Third";
}

(async () => {
  for await (const value of asyncGenerator()) {
    console.log(value); // 输出 "First", "Second", "Third"
  }
})();

2. 处理异步操作
for await...of 可以方便地处理异步操作:

async function* fetchUrls(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    yield response.json();
  }
}

const urls = [
  "https://api.example.com/data1",
  "https://api.example.com/data2",
];

(async () => {
  for await (const data of fetchUrls(urls)) {
    console.log(data);
  }
})();

9.4.3 异步生成器的应用场景

1. 流式数据处理
异步生成器可以用于处理流式数据(如文件读取、网络请求等),逐步产生数据。

2. 异步迭代
通过 for await...of 循环,可以方便地遍历异步生成器产生的值。

3. 复杂异步操作
异步生成器可以简化复杂异步操作的实现,使代码更易读。


9.4.4 示例代码

示例 1:异步生成器

async function* asyncGenerator() {
  yield "First";
  yield "Second";
  yield "Third";
}

(async () => {
  for await (const value of asyncGenerator()) {
    console.log(value); // 输出 "First", "Second", "Third"
  }
})();

示例 2:流式数据处理

async function* readLines(file) {
  const stream = file.stream();
  const reader = stream.getReader();
  const decoder = new TextDecoder();

  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      yield decoder.decode(value);
    }
  } finally {
    reader.releaseLock();
  }
}

(async () => {
  const file = new File(["Line 1\nLine 2\nLine 3"], "example.txt");
  for await (const line of readLines(file)) {
    console.log(line); // 输出 "Line 1", "Line 2", "Line 3"
  }
})();

示例 3:复杂异步操作

async function* fetchData(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    const data = await response.json();
    yield data;
  }
}

const urls = [
  "https://api.example.com/data1",
  "https://api.example.com/data2",
];

(async () => {
  for await (const data of fetchData(urls)) {
    console.log(data);
  }
})();

9.4.5 总结

  • 异步生成器:使用 async function* 定义,通过 yield 产生值。
  • for await...of:用于遍历异步迭代器,处理异步操作。
  • 应用场景:流式数据处理、异步迭代、复杂异步操作。

通过掌握异步生成器和 for await...of,你可以编写更高效、更易读的异步代码。在接下来的学习中,我们将继续探索 JavaScript 的其他高级特性。


思考题

  1. 异步生成器与普通生成器的主要区别是什么?
  2. 如何使用 for await...of 处理流式数据?
  3. 在什么情况下应该使用异步生成器处理复杂异步操作?
#前端开发 分享于 2025-03-21

【 内容由 AI 共享,不代表本站观点,请谨慎参考 】