异步迭代器是next()方法返回promise的对象,需实现[symbol.asynciterator](),配合for await...of使用;普通for...of无法直接遍历它。

async/await 本身不能直接用于 for...in 或 for...of 遍历普通异步迭代器,但 JavaScript 提供了 异步迭代器协议(Async Iteration Protocol),配合 for await...of 语法,就能自然地实现异步遍历。
什么是异步迭代器?
异步迭代器是返回 Promise 的迭代器,其 next() 方法返回 Promise,而不是同步的 { value, done }。要让一个对象支持 for await...of,它必须在 [Symbol.asyncIterator] 上实现一个返回异步迭代器的方法。
例如,一个逐个延迟输出数字的异步可迭代对象:
const asyncCounter = {
[Symbol.asyncIterator]() {
let i = 0;
return {
next() {
if (i // 使用
for await (const num of asyncCounter) {
console.log(num); // 0, 1, 2(依次等待)
}如何从普通数据生成异步迭代器?
常见场景是把数组、fetch 流、数据库游标等转为异步迭代。关键在于封装 next(),让它按需返回 Promise。
- 对数组:可包装成每次 resolve 一个元素(适合模拟分页或节流)
- 对 fetch 响应体:
response.body原生就是异步可迭代的,可直接for await...of读取 chunk - 对数据库查询(如 PostgreSQL 的
pg.Cursor):常提供read()返回 Promise,可据此构建异步迭代器
async/await 在遍历中的实际作用
for await...of 内部会自动 await 每次 next() 的返回值,所以你在循环体内写的 await 是独立于迭代本身的——它控制的是本轮循环内的异步操作,不影响下一轮迭代的触发时机。
比如边请求边处理:
async function* fetchUsers(ids) {
for (const id of ids) {
const res = await fetch(`/api/users/${id}`);
yield await res.json();
}
}
<p>// 使用
for await (const user of fetchUsers([1, 2, 3])) {
console.log(user.name); // 每次都等上一个请求完成后再取下一个
}</p>注意:async function* 是异步生成器函数,会自动返回异步迭代器,是最简洁的创建方式。
错误处理与提前退出
异步遍历中抛出异常会中断循环;也可用 break 或 return 提前退出。若需清理资源(如关闭流、释放连接),应在异步迭代器的 return() 或 throw() 方法中实现(遵循可选的异步迭代器返回协议)。
- try/catch 可包裹整个
for await...of,捕获迭代过程中的 Promise rejection - 迭代器内部的
return()在 break/return 时被调用,适合做 cleanup - 不手动调用
iterator.return(),引擎会在合适时机自动触发











