Skip to content

JavaScript 异步迭代器

在 JavaScript 中,异步迭代器是一种处理异步数据流的机制。它们通过实现 Symbol.asyncIterator 协议,允许逐项处理需要等待的操作(如网络请求或文件读取)。以下是关键概念和具体实现示例:

标准同步迭代器

通过 Symbol.iterator 实现,next() 返回 { value, done } 对象:

javascript
const syncIter = {
  data: [1, 3, 5],
  [Symbol.iterator]() {
    let index = 0
    return {
      next: () => index < this.data.length 
        ? { value: this.data[index++], done: false } 
        : { done: true }
    }
  }
}

for (const num of syncIter) {
  console.log(num) // 依次输出 1, 3, 5
}

生成器函数

function* 创建惰性求值的迭代器,通过 yield 暂停执行:

javascript
function* genFibonacci() {
  let [a, b] = [0, 1]
  while (true) {
    yield a
    ;[a, b] = [b, a + b]
  }
}

const fib = genFibonacci()
console.log(fib.next().value) // 0
console.log(fib.next().value) // 1
console.log(fib.next().value) // 1

异步迭代器

通过 Symbol.asyncIterator 实现,next() 返回 Promise<{ value, done }>

javascript
const asyncPageFetcher = {
  async *[Symbol.asyncIterator]() {
    let page = 1
    while (true) {
      const res = await fetch(`https://api.example.com/data?page=${page}`)
      const data = await res.json()
      if (data.length === 0) break
      yield data
      page++
    }
  }
}

// 使用方式
(async () => {
  for await (const pageData of asyncPageFetcher) {
    console.log('Received page:', pageData)
  }
})()

异步生成器函数

async function* 定义,结合 awaityield 处理异步操作:

javascript
async function* asyncTimer(interval) {
  let count = 0
  while (count < 5) {
    await new Promise(res => setTimeout(res, interval))
    yield `Tick ${++count} at ${new Date().toISOString()}`
  }
}

// 消费异步生成器
(async () => {
  const timer = asyncTimer(1000)
  for await (const msg of timer) {
    console.log(msg) // 每秒输出一条带时间戳的消息
  }
})()

关键差异对比

特性同步迭代器异步迭代器
接口标识符Symbol.iteratorSymbol.asyncIterator
next() 返回值{ value, done }Promise<{ value, done }>
遍历语法for...offor await...of
适用场景内存数据、同步计算网络请求、文件流

实际应用中,异步迭代器常用于处理以下场景:

  1. 分页 API 的连续请求
  2. 大文件流式读取(如 Node.js 的 fs.createReadStream
  3. WebSocket 消息的实时监听
  4. 数据库查询结果的逐批获取

当需要将现有同步迭代器转换为异步版本时,可通过 async function* 包装:

javascript
async function* toAsyncIter(syncIterable) {
  for (const item of syncIterable) {
    yield await Promise.resolve(item)
  }
}

【JavaScript】异步迭代器(Async Iterator):https://segmentfault.com/a/1190000040669160