生成器函数是带暂停能力的函数,通过function和yield实现执行暂停与恢复,返回Generator对象;async function则返回AsyncGenerator,其next()返回Promise,需用for await...of消费。

生成器函数是什么:带暂停能力的函数
生成器函数不是普通函数,它能中途暂停执行、交出控制权,并在后续恢复。关键在于 function* 语法和 yield 表达式——每次遇到 yield,函数就停住,把值“吐出来”,等下次调用 next() 再继续。
它返回一个迭代器对象(Generator),不是直接返回结果。这个对象自带 next()、return()、throw() 方法,是手动控制执行节奏的基础。
用 async function* 实现异步迭代
ES2018 起支持 async function*,它返回的是 AsyncGenerator,其 next() 方法返回 Promise,而不是普通对象。这意味着你可以 await 每次产出,也能在 yield 后面放 Promise(比如 fetch 或数据库查询)。
常见错误是误以为 async function* 能直接 await yield——不行。yield 本身不支持 await,但你可以 yield await someAsyncOp(),或者更常见的是 yield fetch(url),然后在消费端 await 迭代结果。
立即学习“Java免费学习笔记(深入)”;
-
yield后面可以是任意值,包括 Promise;但yield不会自动 await 它 - 消费时必须用
for await...of,不能用普通for...of - 如果生成器内部抛出异步错误(如
fetch失败),需在消费侧用try/catch捕获
async function* fetchPages() {
for (let i = 1; i <= 3; i++) {
const res = await fetch(`/api/items?page=${i}`);
const data = await res.json();
yield data.items;
}
}
// 正确消费方式
(async () => {
for await (const items of fetchPages()) {
console.log(items.length);
}
})();
next() 和 for await...of 的行为差异
next() 是底层接口,每次调用返回 { value, done } 形式的 Promise(对 AsyncGenerator)。而 for await...of 是语法糖,它自动调用 next() 并 await 其返回的 Promise,直到 done: true。
容易踩的坑:手动调用 next() 时忘记 await,导致拿到的是 pending Promise 而非实际值;或在循环中混用 await iterator.next() 和 for await...of,造成重复消费或跳过项。
-
iterator.next()返回Promise -
for await...of隐式处理await和done判断,更安全简洁 - 若需提前终止(如用户取消),可调用
iterator.return(),触发生成器内finally块(如果有)
为什么不用 Promise.all 而用生成器?
因为顺序依赖、流式处理、内存可控。比如拉取分页列表,你不想一次性发 100 个请求,也不愿等全部加载完才开始渲染。生成器让你按需拉取、边拉边用。
另一个典型场景是 WebSocket 消息流或 Node.js 中的 ReadableStream 管道——它们天然适合用 for await...of 消费,而生成器可封装转换逻辑(如过滤、节流、重试)。
注意:async function* 本身不解决错误重试或背压控制,这些得靠额外逻辑实现。比如想对失败的 fetch 自动重试三次,得在生成器内部写循环+try/catch,而不是依赖生成器机制。










