异步生成器(async function*)是优雅实现异步迭代的核心方式,其 next() 返回 promise,天然支持 for await...of;手动实现需确保[symbol.asynciterator]() 返回含 async next() 的对象。

在迭代器中优雅实现异步生成,核心是结合 异步迭代器(Async Iterator)和 异步生成器函数(async function*),而不是在普通同步迭代器里硬塞 await——那会直接报错,因为同步迭代器的 next() 必须返回普通对象,不能返回 Promise。
用 async function* 创建异步生成器
这是最自然、最推荐的方式。异步生成器自动返回一个异步可迭代对象,其 next() 方法返回 Promise,天然适配 for await...of:
- 声明用
async function*,不是function*或async function - 内部可自由使用
await,每次yield的值会被包裹进 Promise 解析结果中 - 无需手动实现
[Symbol.asyncIterator],语法糖已帮你搞定
示例:
async function* fetchUserPages() {for (let page = 1; page const res = await fetch(`/api/users?page=${page}`);
const users = await res.json();
yield users;
}
}
(async () => {
for await (const users of fetchUserPages()) {
console.log('收到一页用户:', users.length);
}
})();
手动实现异步迭代器(适合封装已有逻辑)
当你需要精细控制或包装非生成器逻辑(比如基于事件、流、或已有 Promise 链)时,可手动实现 [Symbol.asyncIterator]:
- 对象必须有
[Symbol.asyncIterator]()方法 - 该方法返回一个对象,该对象有
next()方法 - 这个
next()必须返回Promise
示例(模拟分页请求队列):
const paginatedAPI = {cursor: 0,
[Symbol.asyncIterator]() {
return {
next: async () => {
if (this.cursor >= 3) return { done: true };
this.cursor++;
const data = await fetch(`/data/${this.cursor}`).then(r => r.json());
return { value: data, done: false };
}
}
}
}
(async () => {
for await (const item of paginatedAPI) {
console.log(item);
}
})();
避免常见误区
以下做法不可行或不优雅,需避开:
- 在普通
function*里写await:语法错误,yield和await不能混用在同步生成器中 - 让同步迭代器的
next()返回 Promise:违反迭代器协议,for...of会立即解构失败 - 用
Promise.all([...])包裹普通生成器结果:失去“逐个等待”特性,变成并行拉取,且无法流式消费 - 忘记
for await...of必须在async函数内使用:否则语法报错
与普通生成器的关键区别
对比一目了然:
-
同步生成器:
function*→next()返回{ value, done }→ 用for...of -
异步生成器:
async function*→next()返回Promise→ 用for await...of - 两者都支持
return提前结束,但异步生成器中return值也会被 Promise 包裹
本质上,async/await 在迭代场景中的优雅,正来自它把“等待下一个异步值”这件事,从手动链式调用 .then() 或反复 await iterator.next(),收束为一句清晰的循环语句。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











