17370845950

异步迭代:for await...of循环用法
异步迭代是JavaScript中按需逐步消费异步值的机制,for await...of可在async函数中遍历异步可迭代对象,自动等待每个Promise解析,适用于异步生成器、流数据处理等场景。

在处理异步数据流时,比如从网络请求、文件读取或数据库查询中逐个获取数据,for await...of 循环提供了一种简洁且直观的方式来遍历异步可迭代对象。它适用于返回 Promise 的异步生成器或任何实现了异步迭代协议的对象。

什么是异步迭代?

JavaScript 中的异步迭代允许你按需、逐步地消费异步产生的值。与普通 for...of 不同,for await...of 能自动等待每个异步值的解析完成后再继续下一轮循环。

要支持异步迭代,对象必须实现 [Symbol.asyncIterator] 方法,该方法返回一个包含 next() 方法的对象,而 next() 返回的是 { value, done } 形式的 Promise。

基本语法和使用场景

for await...of 的语法类似于 for...of,但它只能在 async 函数内部使用。

常见用途包括:

  • 读取异步生成的数据(如异步生成器函数)
  • 处理流式数据(如 Node.js 中的 Readable Stream)
  • 分页接口拉取远程数据

示例:使用异步生成器产生延迟数值

async function* generateNumbers() {
  yield await new Promise(resolve => setTimeout(() => resolve(1), 1000));
  yield await new Promise(resolve => setTimeout(() => resolve(2), 1000));
  yield await new Promise(resolve => setTimeout(() => resolve(3), 1000));
}

async function consume() { for await (const num of generateNumbers()) { console.log(num); // 每隔一秒输出 1, 2, 3 } } consume();

处理异步可迭代对象(如 fetch 分块响应)

fetch API 返回的 Response.body 是一个可读流(ReadableStream),它实现了异步迭代器,可用于逐块处理大型响应内容。

示例:逐段读取文本响应

async function readStream() {
  const response = await fetch('https://example.com/large-text');
  const reader = response.body.getReader();
  const decoder = new TextDecoder();

for await (const chunk of readableStreamToAsyncIterable(reader)) { console.log(decoder.decode(chunk)); } }

// 辅助函数:将 ReadableStream 转为异步可迭代对象 function readableStreamToAsyncIterable(reader) { return { [Symbol.asyncIterator]() { return this; }, async next() { const { done, value } = await reader.read(); if (done) return { done: true }; return { value, done: false }; } }; }

注意事项和限制

使用 for await...of 时需注意以下几点:

  • 必须在 async 函数中使用,否则会抛出语法错误
  • 仅适用于实现了异步迭代协议的对象(即有 [Symbol.asyncIterator])
  • 同步可迭代对象(如数组)虽然可以用,但不推荐,因为会造成不必要的 await 开销
  • 无法直接中断异步迭代流,break 和 return 可以退出循环,但不会取消正在进行的操作

基本上就这些。for await...of 让你在面对异步数据流时,代码更清晰、逻辑更连贯,特别适合现代 Web API 和流式处理场景。