跳到主要内容

TypeScript 异步迭代器

在现代JavaScript和TypeScript中,异步编程是一个非常重要的概念。异步迭代器(Async Iterators)是处理异步数据流的一种强大工具。它们允许我们以同步的方式处理异步生成的数据,例如从网络请求、文件读取或数据库查询中获取的数据。

什么是异步迭代器?

异步迭代器是一种特殊的迭代器,它允许我们异步地遍历数据集合。与普通的迭代器不同,异步迭代器的next()方法返回一个Promise,该Promise解析为一个包含valuedone属性的对象。这使得我们可以在异步操作完成后再继续处理下一个值。

异步迭代器的基本结构

一个异步迭代器通常由一个异步生成器函数(Async Generator Function)生成。异步生成器函数使用async function*语法定义,并在函数体内使用yield关键字来生成值。

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

使用异步迭代器

要使用异步迭代器,我们可以使用for await...of循环来遍历异步生成的值。

typescript
async function main() {
for await (const value of asyncGenerator()) {
console.log(value);
}
}

main();

输出:

1
2
3

异步迭代器的实际应用

异步迭代器在处理异步数据流时非常有用。以下是一些常见的应用场景:

1. 从网络请求中获取数据

假设我们有一个API,它返回一个分页的数据流。我们可以使用异步迭代器来逐步获取每一页的数据。

typescript
async function* fetchPaginatedData(url: string) {
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 function main() {
const url = 'https://api.example.com/data';
for await (const pageData of fetchPaginatedData(url)) {
console.log(pageData);
}
}

main();

2. 读取大文件

在处理大文件时,我们可以使用异步迭代器逐行读取文件内容,而不需要一次性将整个文件加载到内存中。

typescript
import * as fs from 'fs';
import * as readline from 'readline';

async function* readFileLines(filePath: string) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});

for await (const line of rl) {
yield line;
}
}

async function main() {
const filePath = 'large-file.txt';
for await (const line of readFileLines(filePath)) {
console.log(line);
}
}

main();

总结

异步迭代器是TypeScript中处理异步数据流的强大工具。它们允许我们以同步的方式处理异步生成的数据,使得代码更加简洁和易于理解。通过for await...of循环,我们可以轻松地遍历异步生成的值,并在实际应用中处理诸如网络请求、文件读取等异步操作。

附加资源与练习

  • 练习1:尝试编写一个异步迭代器,模拟从数据库中分页获取数据的过程。
  • 练习2:使用异步迭代器处理一个实时数据流,例如WebSocket消息。

通过实践这些练习,你将更深入地理解异步迭代器的工作原理,并能够在实际项目中灵活运用它们。