极简三分钟ES6 - ES9中for await of

快递站取快递

想象你同时网购了3件商品(对应3个异步任务)

  • 普通for...of:必须按顺序取快递(等第一个到了才能取第二个)
  • for await...of:快递站到货通知你(哪个先到先取哪个)
js 复制代码
// 模拟三个快递请求  
const fetchPackages = [  
  fetch('//快递1').then(r => r.json()),   
  fetch('//快递2').then(r => r.json()),   
  fetch('//快递3').then(r => r.json())   
];  
 
// 使用for await...of取快递  
async function getDeliveries() {  
  for await (const pkg of fetchPackages) {  
    console.log(` 收到包裹:${pkg.name}`);   
  }  
}  

特性详解

能遍历异步迭代器(Async Iterable)

  • 普通数组/Set/Map → 直接遍历
  • 异步数据源(如网络流/数据库查询)→ 等待每个值完成再继续
js 复制代码
// 创建异步迭代器(每秒生成一个随机数)  
const asyncRandom = {  
  [Symbol.asyncIterator]: async function*() {  
    while(true) {  
      await new Promise(resolve => setTimeout(resolve, 1000));  
      yield Math.random();   
    }  
  }  
};  
 
// 遍历异步迭代器  
(async () => {  
  for await (const num of asyncRandom) {  
    if(num > 0.9) break;  
    console.log(` 当前数值:${num}`);  
  }  
})();  

与同步迭代器的区别

特性 for...of for await...of
迭代器类型 同步迭代器 异步迭代器
等待机制 同步执行 每个值都等待完成
适用数据源 Array/Set/Map等 流/WebSocket/数据库

错误处理:try/catch包裹

js 复制代码
async function readStream() {  
  try {  
    for await (const chunk of networkStream) {  
      process(chunk);  
    }  
  } catch (err) {  
    console.error(" 数据流中断:", err);  
  }  
}  

一些常见的使用场景

分页API的连续请求

js 复制代码
async function getAllPages() {  
  const pageRequests = [  
    fetch('//api?page=1'),  
    fetch('//api?page=2'),  
    fetch('//api?page=3')  
  ];  
    
  // 哪个接口先响应先处理哪个  
  for await (const response of pageRequests) {  
    const data = await response.json();   
    render(data);  
  }  
}  

读取大文件流

js 复制代码
import { createReadStream } from 'fs';  
 
async function readBigFile() {  
  const stream = createReadStream('data.log');   
  for await (const chunk of stream) {  
    console.log(` 收到${chunk.length} 字节数据`);  
  }  
} 

WebSocket消息处理

js 复制代码
const socket = new WebSocket('wss://实时数据');  
 
async function handleMessages() {  
  for await (const msg of socket) { // 需实现异步迭代器  
    if (msg.type  === 'ALERT') notifyUser(msg);  
  }  
}  

数据库批量查询

js 复制代码
async function exportUserData() {  
  const query = db.query('SELECT  * FROM users');  
  for await (const user of query) {  
    writeToCSV(user); // 逐条写入CSV  
  }  
}  

并发任务状态监控

js 复制代码
const tasks = [  
  backupDatabase(), // 返回Promise  
  uploadLogs(),  
  sendEmails()  
];  
 
async function monitorTasks() {  
  for await (const result of tasks) {  
    updateProgressBar(result.taskId);   
  }  
}  

一些特殊场景

同步与异步混合遍历

js 复制代码
const mixedSources = [  
  Promise.resolve(' 异步苹果'),  
  '同步香蕉',  
  Promise.resolve(' 异步橙子')  
];  
 
for await (const item of mixedSources) {  
  console.log(item);  // 正常输出所有值  
}  

提前终止迭代

js 复制代码
// 通过break/return/throw终止  
for await (const data of sensorStream) {  
  if (data.temperature  > 100) {  
    shutdownSystem();  
    break; // 停止监听  
  }  
}

与生成器结合

js 复制代码
async function* genAsyncData() {  
  yield await fetch('//data1');  
  yield await fetch('//data2');  
}  
 
for await (const data of genAsyncData()) {  
  // 处理数据  
}  

与传统方案对比

需求 Promise.all() 方案 for await...of方案 优势
按序处理异步任务 ❌(必须全部完成) ✅(顺序处理) 节省内存,即时处理
处理无限数据流 不可能实现 唯一解决方案
错误处理 单个失败导致全部失败 ✅(可单独捕获) 容错性强
动态添加任务 ✅(可配合数组追加) 灵活扩展

牢记

for await...of = 异步世界的for...of,用同步语法遍历异步集合,数据随到随处理,不积压内存,随时中断/恢复迭代

相关推荐
代码搬运媛6 小时前
Jest 测试框架详解与实现指南
前端
counterxing7 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
wangqiaowq7 小时前
windows下nginx的安装
linux·服务器·前端
之歆7 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
发现一只大呆瓜8 小时前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai108088 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
candyTong8 小时前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
kyriewen9 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor
humcomm10 小时前
元框架的工作原理详解
前端·前端框架
canonical_entropy10 小时前
Attractor Before Harness: AI 大规模开发的方法论
前端·aigc·ai编程