详解 Node.js 中的异步迭代器
什么是异步迭代器?
在 Node.js 中,迭代器(Iterator)是一种数据结构,它会按照一定的顺序,逐个返回集合中的元素。异步迭代器(AsyncIterator)则是迭代器的异步版本,它可以接受 Promise 对象,并使用 async/await
实现异步操作。
异步迭代器是一个实现了 Symbol.asyncIterator
接口的对象,该接口会返回包含 next
方法的对象。每次调用 next
方法时,都会返回一个 Promise 对象,该 Promise 对象的值会包含 value
(当前元素的值)和 done
(一个布尔值,表示异步迭代器是否已完成)属性。
如何使用异步迭代器?
使用异步迭代器主要分为两个步骤:
- 实现异步迭代器
- 使用
for await...of
循环异步迭代器
下面分别对这两个步骤进行详细讲解。
实现异步迭代器
首先,必须实现一个异步迭代器对象,该对象至少包含一个 Symbol.asyncIterator
方法,以及一个 next
方法。
下面是一个简单的示例:
const asyncIterableObj = {
[Symbol.asyncIterator]() {
let count = 0;
return {
async next() {
await new Promise(resolve => setTimeout(resolve, 1000));
count++;
if (count <= 5) {
return { value: count, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
该示例实现了一个简单的异步迭代器对象,每次调用 next
方法时,都会返回一个 Promise 对象,并且等待一秒钟后返回一个包含当前计数值的对象。当计数值超过 5
时,会返回一个 done
属性为 true
的对象,表示异步迭代器已完成。
使用 for await...of
循环异步迭代器
实现异步迭代器后,就可以使用 for await...of
循环遍历异步迭代器对象了。
下面是一个示例:
async function main() {
for await (let num of asyncIterableObj) {
console.log(num);
}
console.log('done!');
}
main();
使用上面定义好的异步迭代器对象,调用 main
函数后,会依次输出从 1
到 5
的数字,最后输出一个 done!
字符串。
示例说明
下面给出两个实际的例子,说明异步迭代器的使用场景。
示例 1:异步文件读取
const fs = require('fs');
const asyncIterableObj = {
[Symbol.asyncIterator]() {
const lines = fs.readFileSync('test.txt', 'utf-8').split('\n');
let index = 0;
return {
async next() {
if (index < lines.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
return { value: lines[index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
async function main() {
for await(let line of asyncIterableObj) {
console.log(line);
}
}
main();
该示例读取文件 test.txt
中的内容,并使用异步迭代器逐行输出,每次暂停 1 秒钟。
示例 2:异步数据请求
const fetch = require('node-fetch');
const asyncIterableObj = {
[Symbol.asyncIterator]() {
let pageNum = 0;
let data = [];
return {
async next() {
if (data.length === 0) {
const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_page=${++pageNum}`);
data = await res.json();
}
if (data.length > 0) {
return { value: data.shift(), done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
async function main() {
for await(let photo of asyncIterableObj) {
console.log(photo.title);
}
}
main();
该示例从 https://jsonplaceholder.typicode.com/photos
接口中获取数据,并使用异步迭代器逐个输出每个图片的标题。每次从接口中请求一页数据,一次获取多个数据,等所有数据遍历完后,再请求下一页数据。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解nodejs中的异步迭代器 - Python技术站