摘要:在本教程中,您将学习有关 JavaScript 异步迭代器的知识,这些迭代器允许您按顺序访问异步数据。
JavaScript 异步迭代器简介
ES6 引入了 迭代器 接口,允许您按顺序访问数据。迭代器非常适合访问同步数据源,如 数组、集合 和 映射。
迭代器接口的主要方法是 next()
,它返回 {value, done}
对象,其中 done
是一个布尔值,表示是否已到达序列的末尾,而 value
是序列中产生的值。
同步数据意味着序列中的下一个 value
和 done
状态在 next()
方法返回时是已知的。
除了同步数据源之外,JavaScript 通常还需要访问异步数据源,例如 I/O 访问。对于异步数据源,迭代器的 value
和 done
状态在 next()
方法返回时通常是未知的。
为了处理异步数据源,ES2018 引入了异步迭代器(或异步迭代器)接口。
异步迭代器类似于迭代器,只是它的 next()
方法返回一个 promise,该 promise 解析为 {value, done}
对象。
以下说明了实现迭代器接口的 Sequence
类。(查看 迭代器教程,了解有关如何实现 Sequence
类的更多信息。)
class Sequence {
constructor(start = 0, end = Infinity, interval = 1) {
this.start = start;
this.end = end;
this.interval = interval;
}
[Symbol.iterator]() {
let counter = 0;
let nextIndex = this.start;
return {
next: () => {
if (nextIndex <= this.end) {
let result = {
value: nextIndex,
done: false
}
nextIndex += this.interval;
counter++;
return result;
}
return {
value: counter,
done: true
};
}
}
}
}
Code language: JavaScript (javascript)
为了使此 Sequence
类异步化,您需要对其进行如下修改
- 使用
Symbol.asyncIterator
而不是Symbol.iterator
- 从
next()
方法返回 Promise。
以下代码将 Sequence
类转换为 AsyncSequence
类
class AsyncSequence {
constructor(start = 0, end = Infinity, interval = 1) {
this.start = start;
this.end = end;
this.interval = interval;
}
[Symbol.asyncIterator]() {
let counter = 0;
let nextIndex = this.start;
return {
next: async () => {
if (nextIndex <= this.end) {
let result = {
value: nextIndex,
done: false
}
nextIndex += this.interval;
counter++;
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result);
}, 1000);
});
}
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
value: counter,
done: true
});
}, 1000);
});
}
}
}
}
Code language: JavaScript (javascript)
AsyncSequence
每隔 1 秒返回序列中的下一个数字。
for await...of 语句
为了迭代异步可迭代对象,ES2018 引入了 for await...of
语句
for await (variable of iterable) {
// statement
}
Code language: JavaScript (javascript)
由于我们只能在 async
函数中使用 await
关键字,因此我们可以创建一个异步 IIFE,该函数使用 AsyncSequence
类,如下所示
(async () => {
let seq = new AsyncSequence(1, 10, 1);
for await (let value of seq) {
console.log(value);
}
})();
Code language: JavaScript (javascript)
输出(每个数字在每秒之后返回)
1
2
3
4
5
6
7
8
9
10
Code language: JavaScript (javascript)
下表说明了迭代器和异步迭代器之间的差异
# | 迭代器 | 异步迭代器 |
---|---|---|
众所周知的符号 | Symbol.iterator | Symbol.asyncIterator |
next() 返回值是 | {value, done } | Promise 解析为 {value, done} |
循环语句 | for...of | for await...of |