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 的其他高级特性。
思考题:
- 异步生成器与普通生成器的主要区别是什么?
- 如何使用
for await...of处理流式数据? - 在什么情况下应该使用异步生成器处理复杂异步操作?
#前端开发
分享于 2025-03-21