JavaScript迭代器和生成器本身是同步协议,但async function*可创建AsyncIterator,配合for await...of实现异步遍历;需注意yield非return、done:true为终止信号、不可混用async与普通for...of。

JavaScript 的迭代器和生成器本身不简化异步——它们是同步协议,但能被 async 修饰后成为 AsyncIterator,再配合 for await...of 实现“看起来像同步”的异步遍历。直接拿 function* 去处理 Promise 链,不加 async 会出错。
迭代器对象必须实现 next() 方法
一个迭代器是一个有 next() 方法的对象,该方法返回形如 { value, done } 的对象。它不关心数据怎么来,只承诺每次调用都推进并返回下一个状态。
常见错误:手动实现迭代器时忘记在末尾返回 { value: undefined, done: true },导致循环卡死或无限重复最后一项。
-
done: true是终止信号,不是可选提示 - 数组的
[Symbol.iterator]()返回的就是标准迭代器 - 自定义类想支持
for...of,必须在[Symbol.iterator]方法里返回迭代器对象
function* 生成器函数返回迭代器,不是执行函数体
调用 function* () {} 只创建并返回一个迭代器对象,函数体代码不会立即运行。只有第一次调用 next() 才开始执行,遇到 yield 暂停,并把 yield 后的值作为 value 返回。
立即学习“Java免费学习笔记(深入)”;
容易踩的坑:
-
yield不是return,函数没结束,上下文(变量、执行位置)被保留 - 多次调用
next()会从上次暂停处继续,直到函数退出或遇到return - 生成器不能被
new调用,会报TypeError: Generator is not a constructor
function* countdown(n) {
while (n > 0) yield n--;
}
const iter = countdown(3);
iter.next(); // { value: 3, done: false }
iter.next(); // { value: 2, done: false }
iter.next(); // { value: 1, done: false }
iter.next(); // { value: undefined, done: true }
async function* 创建异步迭代器,需用 for await...of
普通生成器无法 await,但加上 async 关键字后,yield 可以产出 Promise,且整个函数返回的是 AsyncIterator,其 next() 方法返回 Promise。
关键约束:
- 不能混用
async function*和普通for...of,会得到 pending Promise 而非解包后的值 -
for await...of内部自动await每次next().value,但要求可迭代对象满足[Symbol.asyncIterator]接口 - Node.js 早于 v10.0.0 不支持
AsyncIterator,浏览器中需 Chrome 63+ / Firefox 57+
async function* fetchLines(url) {
const response = await fetch(url);
const reader = response.body.getReader();
let { value, done } = await reader.read();
while (!done) {
yield new TextDecoder().decode(value);
({ value, done } = await reader.read());
}
}
// 正确用法:
for await (const line of fetchLines('/log.txt')) {
console.log(line);
}
真正让异步“变简单”的不是生成器本身,而是语言层面对 AsyncIterator 协议的支持——它把流式异步数据(比如 HTTP 流、EventSource、数据库游标)统一成可遍历结构。漏掉 async 或误用 for...of 就会掉进 Promise 套娃陷阱。











