TypeScript/JavaScript 中的异步迭代语句

for await...of 是 TypeScript/JavaScript 中的异步迭代语句,专门用于遍历异步可迭代对象(Async Iterable)。

基本语法

for await (const item of asyncIterable) {
  // 处理每个异步获取的值
}

与普通 for...of 的区别

特性 for...of for await...of
迭代对象 同步可迭代对象 异步可迭代对象
返回值 同步值 Promise 解析后的值
使用场景 数组、Map、Set等 异步流、生成器等

使用场景

1. 处理异步生成器函数

async function* asyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}

async function process() {
  for await (const value of asyncGenerator()) {
    console.log(value); // 1, 2, 3
  }
}

2. 处理多个 Promise 的集合

async function fetchUrls(urls: string[]) {
  for await (const response of urls.map(url => fetch(url))) {
    const data = await response.json();
    console.log(data);
  }
}

3. Node.js 流处理

import { createReadStream } from 'fs';
import { createInterface } from 'readline';

async function readLargeFile() {
  const fileStream = createReadStream('large-file.txt');
  const rl = createInterface({
    input: fileStream,
    crlfDelay: Infinity
  });

  for await (const line of rl) {
    console.log(line); // 逐行处理大文件
  }
}

4. Web Streams API

async function processStream(stream: ReadableStream) {
  const reader = stream.getReader();
  
  try {
    for await (const chunk of stream) {
      console.log('Received chunk:', chunk);
    }
  } finally {
    reader.releaseLock();
  }
}

实际示例:批量处理异步任务

// 模拟异步数据源
async function* fetchPaginatedData(pageSize: number = 10) {
  let page = 0;
  let hasMore = true;
  
  while (hasMore) {
    // 模拟 API 调用
    const data = await fetchDataFromAPI(page, pageSize);
    yield data.items;
    
    hasMore = data.hasMore;
    page++;
  }
}

async function processAllData() {
  const results = [];
  
  for await (const items of fetchPaginatedData()) {
    // 等待所有项目的处理完成
    const processed = await Promise.all(
      items.map(async item => processItem(item))
    );
    results.push(...processed);
  }
  
  return results;
}

注意事项

  1. 必须在 async 函数中使用

    // ❌ 错误:不能在同步函数中使用
    function syncFunction() {
      for await (const item of asyncIterable) { ... }
    }
    
    // ✅ 正确:必须在 async 函数中
    async function asyncFunction() {
      for await (const item of asyncIterable) { ... }
    }
    
  2. 错误处理

    async function processWithErrorHandling() {
      try {
        for await (const item of asyncIterable) {
          // 处理每个项目
        }
      } catch (error) {
        console.error('迭代过程中出错:', error);
      }
    }
    
  3. 与 Promise.all() 的区别

    • for await...of:顺序处理,等待前一个完成
    • Promise.all():并行处理,等待所有完成

底层原理

for await...of 实际上是对异步迭代器的语法糖:

// for await...of 的等价实现
async function manualAsyncIteration(asyncIterable) {
  const iterator = asyncIterable[Symbol.asyncIterator]();
  
  try {
    while (true) {
      const { value, done } = await iterator.next();
      if (done) break;
      // 使用 value
    }
  } finally {
    if (iterator.return) await iterator.return();
  }
}

浏览器和 Node.js 支持

  • ES2018+ 标准
  • Node.js 10.0.0+ 完全支持
  • 现代浏览器支持(除 IE 外)

for await...of 是处理异步数据流的强大工具,特别适合处理分页 API、文件流、WebSocket 消息等场景。

posted @ 2026-02-06 20:04  悠哉大斌  阅读(10)  评论(0)    收藏  举报