必须使用 symbol.asynciterator 而非 symbol.iterator 实现异步可迭代对象,因前者返回 promise,后者仅支持同步返回;需用计算属性名语法定义 [symbol.asynciterator]() 方法。

不能直接用 Symbol.iterator 实现“异步可迭代对象”,因为标准的 Symbol.iterator 必须返回同步迭代器(即 next() 方法返回 { value, done } 普通对象),而异步迭代器要求 next() 返回 Promise,需使用 Symbol.asyncIterator。
必须用 Symbol.asyncIterator,而非 Symbol.iterator
JavaScript 规范明确区分:
-
[Symbol.iterator]→ 同步迭代协议,用于for...of、扩展运算符等 -
[Symbol.asyncIterator]→ 异步迭代协议,用于for await...of
试图在 [Symbol.iterator] 中返回 Promise 会导致运行时错误或静默失败。真正可行的是利用计算属性名语法定义 [Symbol.asyncIterator] 方法。
用计算属性名定义 asyncIterator 方法
计算属性名([key])允许动态使用 symbol 作为键,这是声明自定义异步迭代器的标准写法:
class AsyncCounter {
constructor(max) {
this.max = max;
}
// ✅ 正确:使用计算属性名 + Symbol.asyncIterator
[Symbol.asyncIterator]() {
let i = 0;
return {
next: () => {
if (i
<p>这样构造的对象就支持 <code>for await...of</code>:</p>
<pre class="brush:js;toolbar:false;">const counter = new AsyncCounter(3);
for await (const num of counter) {
console.log(num); // 0, 1, 2
}
结合生成器函数简化实现(推荐)
手动写 next() 容易出错。更简洁可靠的方式是用 async function*(异步生成器),它自动返回符合 Symbol.asyncIterator 协议的对象:
class AsyncDataLoader {
constructor(urls) {
this.urls = urls;
}
// ✅ 推荐:async generator 自动满足 Symbol.asyncIterator
async *[Symbol.asyncIterator]() {
for (const url of this.urls) {
const res = await fetch(url);
const data = await res.json();
yield data;
}
}
}
无需手动实现迭代器对象,语法清晰,天然支持 await 和 yield。
注意事项与常见误区
实际使用中需注意:
-
Symbol.asyncIterator是不可枚举、不可配置的内置 symbol,必须严格拼写,不能写成字符串"Symbol.asyncIterator" - 异步迭代器不兼容传统
for...of,会报TypeError: X is not iterable - 若需同时支持同步和异步迭代,需分别实现
[Symbol.iterator]和[Symbol.asyncIterator](但语义通常不同,慎用) - Babel/TypeScript 转译需开启
es2018或更高目标,确保Symbol.asyncIterator不被抹除










