hand
_1_11_288
4
返回栏目
0k
2k
1k
2k
1k
1k
1k
2k
2k
2k
1k
2k
1k
2k
1k
1k
1k
1k
1k
2k
1k
1k
1k
1k
1k
1k
1k
1k
1k
2k
1k
1k
1k
1k
1k
1k
1k
1k
1k
2k
1k
1k
1k
1k
1k
1k
1k
2k
1k
2k
1k
1k
1k
1k
1k
1k
1k
2k
2k
1k
1k
1k
2k
1k
1k
2k
2k
1k
1k
1k
2k
1k
1k
2k
2k
1k
2k
1k
1k
2k
2k
2k
3k
3k
2k
3k
2k
3k
3k
3k
1k
2k
3k
2k
2k
3k
3k
2k
2k
6k
3k
2k
2k
5k
3k
4k
3k
3k
2k
4k
3k
3k
2k
3k
3k
1k
4k
4k
4k
2k
5k
3k
2k
3k
4k
3k
3k
4k
2k
3k
3k
4k
2k
2k
3k
4k
3k
3k
2k
5k
2k
3k
3k
3k
3k
2k
3k
3k
3k
2k
2k
2k
2k
3k
2k
2k
2k
3k
2k
2k
2k
2k
2k
2k
0.1k
0.2k
3k
2k
3k
2k
0.1k
2k
2k
4k
2k
2k
1k
2k
2k
3k
3k
3k
3k
2k
2k
3k
3k
3k
4k
3k
3k
4k
3k
2k
2k
3k
3k
3k
3k
3k
3k
2k
3k
3k
4k
4k
3k
3k
2k
2k
3k
2k
2k
1k
2k
3k
1k
2k
2k
2k
2k
2k
2k
2k
2k
2k
4k
2k
3k
2k
1k
2k
2k
2k
2k
2k
3k
2k
3k
1k
2k
2k
2k
0k
2k
2k
2k
2k
2k
2k
2k
3k
2k
2k
1k
1k
3k
2k
3k
1k
2k
1k
2k
2k
2k
2k
3k
1k
3k
2k
2k
2k
2k
2k
2k
1k
2k
2k
4k
3k
3k
2k
2k
2k
2k
2k
2k
4k
3k
3k
3k
2k
2k
2k
2k
2k
2k
3k
4k
返回前端 - Javascript栏目
作者:
贺及楼
成为作者
更新日期:2025-02-21 21:20:22
在 JavaScript 的世界里,异步编程一直是核心主题之一。随着 Web 应用的复杂度不断提升,处理异步数据流变得愈发重要。异步可迭代接口就是为了更优雅地处理异步数据流而引入的特性,下面我们就来深入了解它。
在了解异步可迭代接口之前,我们先回顾一下可迭代协议。可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,比如 for...of
循环如何遍历这些对象。一个对象要成为可迭代对象,必须实现 Symbol.iterator
方法,该方法返回一个迭代器对象。
const iterableObj = {
[Symbol.iterator]() {
let count = 0;
return {
next() {
if (count < 3) {
return { value: count++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (let value of iterableObj) {
console.log(value);
}
在这个例子中,iterableObj
实现了 Symbol.iterator
方法,因此可以使用 for...of
循环进行遍历。
异步可迭代协议是可迭代协议的异步版本,它允许对象定义或定制它们的异步迭代行为。一个对象要成为异步可迭代对象,必须实现 Symbol.asyncIterator
方法,该方法返回一个异步迭代器对象。异步迭代器对象必须有一个 next()
方法,该方法返回一个 Promise
,这个 Promise
会 resolve 为一个对象,该对象有 value
和 done
两个属性,和同步迭代器类似。
const asyncIterableObj = {
[Symbol.asyncIterator]() {
let count = 0;
return {
next() {
return new Promise((resolve) => {
setTimeout(() => {
if (count < 3) {
resolve({ value: count++, done: false });
} else {
resolve({ value: undefined, done: true });
}
}, 1000);
});
}
};
}
};
(async () => {
for await (let value of asyncIterableObj) {
console.log(value);
}
})();
在这个例子中,asyncIterableObj
实现了 Symbol.asyncIterator
方法,返回一个异步迭代器。使用 for await...of
循环可以异步地遍历这个对象。每次迭代都会等待 next()
方法返回的 Promise
被 resolve,然后处理结果。
当需要逐行读取大文件时,使用异步可迭代可以避免一次性将整个文件加载到内存中。例如,在 Node.js 中可以这样实现:
const fs = require('fs');
const readline = require('readline');
function readLines(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
return {
[Symbol.asyncIterator]() {
return {
next() {
return new Promise((resolve) => {
rl.once('line', (line) => {
resolve({ value: line, done: false });
});
rl.once('close', () => {
resolve({ value: undefined, done: true });
});
});
}
};
}
};
}
(async () => {
for await (let line of readLines('largeFile.txt')) {
console.log(line);
}
})();
在处理分页数据时,我们可以使用异步可迭代来逐个请求每一页的数据。
async function fetchPage(page) {
const response = await fetch(`https://api.example.com/data?page=${page}`);
return await response.json();
}
function paginatedData() {
let page = 1;
return {
[Symbol.asyncIterator]() {
return {
async next() {
try {
const data = await fetchPage(page++);
if (data.length === 0) {
return { value: undefined, done: true };
}
return { value: data, done: false };
} catch (error) {
throw error;
}
}
};
}
};
}
(async () => {
for await (let pageData of paginatedData()) {
console.log(pageData);
}
})();
协议 | 必须实现的方法 | 返回值 | 使用的循环语句 |
---|---|---|---|
可迭代协议 | Symbol.iterator |
迭代器对象 | for...of |
异步可迭代协议 | Symbol.asyncIterator |
异步迭代器对象(next() 方法返回 Promise ) |
for await...of |
next()
方法返回的 Promise
被 reject,整个迭代过程会终止。因此,需要在适当的地方进行错误处理。异步可迭代接口为我们处理异步数据流提供了一种简洁、优雅的方式。通过实现 Symbol.asyncIterator
方法,我们可以让对象支持异步迭代,从而更方便地处理异步操作。无论是读取大文件还是分页数据请求,异步可迭代接口都能发挥重要作用。
前端 - Javascript
整章节共299节
快分享给你的小伙伴吧 ~