极简三分钟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,用同步语法遍历异步集合,数据随到随处理,不积压内存,随时中断/恢复迭代

相关推荐
Moonbeam Community几秒前
应用爆发,DeFi先行
javascript·ide·web3·区块链·polkadot
2301_796512524 分钟前
使用状态管理、持久化存储或者利用现有的库来辅助React Native鸿蒙跨平台开发开发一个允许用户撤销删除的操作
javascript·react native·react.js
全马必破三9 分钟前
浏览器原理知识点总结
前端·浏览器
零Suger10 分钟前
React 组件通信
前端·react.js·前端框架
LYFlied14 分钟前
【每日算法】 LeetCode 394. 字符串解码
前端·数据结构·算法·leetcode·面试·职场和发展
前端不太难21 分钟前
RN Navigation vs Vue Router 的架构对比
javascript·vue.js·架构
硕子鸽24 分钟前
UniApp + Dify 实战:详解 SSE 流式响应的解析与前端渲染
前端·uni-app·dify
lxh011324 分钟前
复原IP地址
前端·数据结构·算法
小白学大数据26 分钟前
Python 爬虫如何分析并模拟 JS 动态请求
开发语言·javascript·爬虫·python