for-await-of 是用于消费异步迭代器的语法,按需拉取、顺序等待、自动处理拒绝;它不控制并发,需在迭代器内部实现节流与资源清理,并在内部处理错误重试。

for-await-of 是 JavaScript 中专为异步迭代器设计的语法,它能自然地消费 AsyncIterator 对象(比如由 async function* 生成的异步生成器),逐个等待每个 Promise 解析后再继续下一次迭代。它不是用来“控制”数据流的开关,而是**按需拉取、顺序等待、自动处理拒绝**的消费方式。
理解 for-await-of 的基本行为
它内部调用异步迭代器的 next() 方法,并 await 其返回的 Promise,直到 done: true 才退出循环。遇到任意一次 next() 返回被拒绝的 Promise,循环会立即抛出错误(可被 try/catch 捕获)。
例如:
async function* fetchPosts() {yield await fetch('/api/post/1').then(r => r.json());
yield await fetch('/api/post/2').then(r => r.json());
}
for await (const post of fetchPosts()) {
console.log(post.title); // 每次都等上一个请求完成才发起下一个
}
实现节流与并发控制
for-await-of 本身不提供并发控制,但你可以把“可控的异步迭代器”作为它的数据源。常见做法是封装一个限并发的异步可迭代对象:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 用
Promise.allSettled或Promise.race手动管理一批任务 - 用
async-pool等库生成带并发限制的异步迭代器 - 自己写一个异步迭代器,在
next()中检查当前运行中的请求数,未达上限才发起新请求
关键点:控制逻辑写在迭代器内部(如 async function* 的函数体里),而不是写在 for await 循环里。
提前终止与清理资源
异步迭代器支持 return() 和 throw() 方法。for await 循环在被 break、return 或异常中断时,会自动调用迭代器的 return()(如果存在),可用于释放资源:
const handles = [];
try {
for (const p of paths) {
const handle = await openFile(p);
handles.push(handle);
yield await readFile(handle);
}
} finally {
for (const h of handles) await h.close();
}
}
// break 会触发上面的 finally
for await (const data of streamFiles(['/a.txt', '/b.txt'])) {
if (data.includes('STOP')) break;
console.log(data);
}
注意错误传播与重试逻辑
单次 yield 出错(如 yield Promise.reject(...))会导致 for await 抛出异常并退出。如需重试,必须在异步迭代器内部处理:
- 在
async function*中用try/catch包裹异步操作,失败后可重试或跳过 - 避免在
for await循环体内直接await可能失败的 Promise —— 那会脱离迭代器的错误上下文 - 若需跳过某次失败项,让迭代器
continue而非throw,否则循环终止
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










