异步迭代是JavaScript中按需逐步消费异步值的机制,for await...of可在async函数中遍历异步可迭代对象,自动等待每个Promise解析,适用于异步生成器、流数据处理等场景。

在处理异步数据流时,比如从网络请求、文件读取或数据库查询中逐个获取数据,for await...of 循环提供了一种简洁且直观的方式来遍历异步可迭代对象。它适用于返回 Promise 的异步生成器或任何实现了异步迭代协议的对象。
什么是异步迭代?
JavaScript 中的异步迭代允许你按需、逐步地消费异步产生的值。与普通 for...of 不同,for await...of 能自动等待每个异步值的解析完成后再继续下一轮循环。
要支持异步迭代,对象必须实现 [Symbol.asyncIterator] 方法,该方法返回一个包含 next() 方法的对象,而 next() 返回的是 { value, done } 形式的 Promise。
基本语法和使用场景
for await...of 的语法类似于 for...of,但它只能在 async 函数内部使用。
常见用途包括:
- 读取异步生成的数据(如异步生成器函数)
- 处理流式数据(如 Node.js 中的 Readable Stream)
- 分页接口拉取远程数据
示例:使用异步生成器产生延迟数值
async function* generateNumbers() {
yield await new Promise(resolve => setTimeout(() => resolve(1), 1000));
yield await new Promise(resolve => setTimeout(() => resolve(2), 1000));
yield await new Promise(resolve => setTimeout(() => resolve(3), 1000));
}
async function consume() {
for await (const num of generateNumbers()) {
console.log(num); // 每隔一秒输出 1, 2, 3
}
}
consume();
处理异步可迭代对象(如 fetch 分块响应)
fetch API 返回的 Response.body 是一个可读流(ReadableStream),它实现了异步迭代器,可用于逐块处理大型响应内容。
示例:逐段读取文本响应
async function readStream() {
const response = await fetch('https://example.com/large-text');
const reader = response.body.getReader();
const decoder = new TextDecoder();
for await (const chunk of readableStreamToAsyncIterable(reader)) {
console.log(decoder.decode(chunk));
}
}
// 辅助函数:将 ReadableStream 转为异步可迭代对象
function readableStreamToAsyncIterable(reader) {
return {
[Symbol.asyncIterator]() {
return this;
},
async next() {
const { done, value } = await reader.read();
if (done) return { done: true };
return { value, done: false };
}
};
}
注意事项和限制
使用 for await...of 时需注意以下几点:
- 必须在 async 函数中使用,否则会抛出语法错误
- 仅适用于实现了异步迭代协议的对象(即有 [Symbol.asyncIterator])
- 同步可迭代对象(如数组)虽然可以用,但不推荐,因为会造成不必要的 await 开销
- 无法直接中断异步迭代流,break 和 return 可以退出循环,但不会取消正在进行的操作
基本上就这些。for await...of 让你在面对异步数据流时,代码更清晰、逻辑更连贯,特别适合现代 Web API 和流式处理场景。










