惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
AI
AI
S
Security Affairs
S
Secure Thoughts
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Heimdal Security Blog
Forbes - Security
Forbes - Security
Security Archives - TechRepublic
Security Archives - TechRepublic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Spread Privacy
Spread Privacy
C
Cybersecurity and Infrastructure Security Agency CISA
Latest news
Latest news
T
Tor Project blog
I
Intezer
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Project Zero
Project Zero
V2EX - 技术
V2EX - 技术
V
Vulnerabilities – Threatpost
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Hacker News: Ask HN
Hacker News: Ask HN
S
Schneier on Security
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
T
Threatpost
Help Net Security
Help Net Security
W
WeLiveSecurity
Know Your Adversary
Know Your Adversary
WordPress大学
WordPress大学
L
LINUX DO - 最新话题
月光博客
月光博客
PCI Perspectives
PCI Perspectives
小众软件
小众软件
爱范儿
爱范儿
博客园 - Franky
Security Latest
Security Latest
Microsoft Azure Blog
Microsoft Azure Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News
Scott Helme
Scott Helme
P
Privacy International News Feed
Y
Y Combinator Blog
P
Palo Alto Networks Blog
M
MIT News - Artificial intelligence
N
Netflix TechBlog - Medium

博客园 - lzhdim

近十年最帅风冷!酷冷至尊V8 ACE 3DHP散热器评测:单塔能干翻双塔 20260723 - 个人小作品更新 C# 中读取CPU、硬盘和内存温度 雷柏VT3s MAX鼠标评测:中小手型用户也没有被遗忘 顶尖性能的小号电竞鼠标来了 JavaScript 中的原型与继承 1分钟查清局域网所有IP 20260714 - 个人小作品更新 WorkBuddy 完整教程手册 专为AI而生的企业级QLC SSD!长江存储PE501 61.44TB评测:超过1PB的写入测试 32GB显存才是第一生产力!英特尔锐炫 Pro B70评测:中小企业AI降本神器 JavaScript中的this关键字 C#开发的PopoSaver泡泡屏保应用 - 开源研究系列文章 - 个人小作品 6天不间断测试告诉你到底有多省电!米家空调巨省电大1.5匹评测:制冷峰值功率不超过500W 三倍双摄加持 + D-Log 2 曲线!大疆DJI OSMO Pocket 4P全面评测:补齐短板,化身口袋电影机 晶栈4.0闪存立威!长江存储致态TiPro9000 2TB SSD评测:缓外写入超4GB/s独一档 C# 多线程同步机制详解:原理、使用与性能对比 JavaScript作用域与闭包讲解 最受欢迎的 10 大免费 AI 工具 六种AI生意,从月入一万到月入十万 5个国产大模型实测对比2026:DeepSeek、Kimi、豆包、通义、智谱哪个好用 豆包、元宝、千问、Kimi、DeepSeek,这么多AI软件,到底该用哪个? 微软免费开源了一个 Linux 操作系统,没错!是微软出品 一次看懂5种咖啡冲煮方式:意式、手冲、法压、冷萃、摩卡壶到底有什么区别 120个 实用CSS 技巧汇总合集 JavaScript运算符与表达式详解 C#开发的ScreenSaver屏保应用 - 开源研究系列文章 - 个人小作品 WinForm 中跨线程操作 UI 的解决方案 JavaScript变量与数据类型详解 苹果良心!iOS 27适配设备公布:30款机型 7年前的iPhone 11还能升级 C++图形用户界面开发入门 10个不该免费的GitHub神级项目 JavaScript语言全面概述:从历史到现代实践 一张图看懂常见咖啡 C盘空间多出来4GB:谷歌服软 Chrome本地AI大模型可禁用、删除了 96GB显存运行230B大模型!七彩虹灵创K16笔记本评测:160W性能释放 AMD锐龙AI Max+ 395加持全能移动AI工作站 AI PC最强存储搭档!雷克沙NM1090 PRO 8TB固态评测:14400MB/s满速不缩水 C#已经不是当年的C#了——我用它写了个微秒级数据库引擎 EasyTool:轻量全能的 .NET 工具类库 SQL 入门 17:MySQL 数据类型:从字符串到 JSON 的全面解析 SQL 入门 16:SQL 事务隔离级别与死锁解析(易懂) 原相3955XM+TL3228主控!小米电竞鼠标2全面评测:原生双8K究竟有多强 PCIe 4.0火力全开:闪迪奥丁马仕GX 7100 NVMe SSD上手 超乎预料的千元级电竞主板!七彩虹iGame B850M Ultra-OC V14主板评测 SQL 入门 15:SQL 事务:从 ACID 到四种常见的并发问题 名人 - 我的闪存 C#性能优化技巧 SQL 入门 14:SQL 触发器与事件:自动化数据处理 38个实用的JavaScript 技巧 一款基于 .Net WinForm 开发的节点编辑器,纯 GDI 实现,体积仅 100+Kb Masuit.Tools:这个 C# 工具库 SQL 入门 13:SQL 存储过程与函数:封装逻辑与参数处理 49个 JavaScript 代码快捷技巧,让你在 2026 年成为代码高手 20260503 - 个人小作品更新 SQL 入门 12:SQL 视图:创建、修改与可更新视图 C#如何实现Windows系统桌面截图功能... 6999元AMD新旗舰首测!锐龙9 9950X3D2性能解禁:这颗U根本不是给游戏玩家造的 SQL 入门 11:日期时间格式化、IF、CASE的使用 基于C#的校时类库的实现及使用 - 开源项目研究文章 39g无打孔+原生双8K!雷柏VT0 Air MAX / VT3s Air MAX鼠标评测:轻到飞起还快到极致 WinForm 中控件自适应窗体变化 20260413 - 个人小作品更新 SQL 入门 10:SQL 内置函数:数值、字符串与时间处理 最强麒麟芯+自研风冷 华为Mate80 Pro MAX 风驰版全面评测:涡轮散热封神 性能稳到骨子里 WiFi8核心技术特性与性能分析 2026年最新AMD/Intel桌面CPU排名:多线程、单线程、游戏性能谁才是第一 用DG对C盘进行扩容 - 初学者系列 - 学习者系列 还有比它更强的OEM固态吗!长江存储PC550 1TB评测:不用散热片也能满速的PCIe 5.0 SSD SharpCompress:跨平台的 C# 压缩与解压库 SQL 入门 9:SQL 高级子查询:ANY、EXISTS 与多位置应用 盘点接私活20个最实用的 .NET 开源项目 C#中加载图片的资源释放 20260404 - 个人小作品更新 开启iphone的墙纸玻璃效果 可能是综合性能最强的PCIe 5.0 SSD!铠侠EXCERIA PRO G2 2TB评测:AIDA64线性写入全程不掉速 SQL 入门 8:SQL 复杂查询:子查询与ALL关键词 性能最强的锐龙AI 9 H 465轻薄本!华硕无畏Pro16锐龙版2026评测 4盘RAID 0读写超1100MB/s!希捷酷狼Pro 32TB硬盘评测:百万文件快速完成备份 项目(Project)、项目集(Program)、项目组合(Portfolio) SQL 入门 7:SQL 聚合与分组:函数、GROUP BY 与 ROLLUP
JavaScript异步编程的演进
lzhdim · 2026-07-27 · via 博客园 - lzhdim

一、 为什么需要异步编程?先说说为什么要有异步这回事. JavaScript是单线程的, 也就是说它一次只能做一件事. 如果所有操作都同步执行, 遇到网络请求或者文件读取这种耗时的操作, 页面就会卡住不动, 用户体验直接爆炸. 

// 同步代码的灾难现场const data = fetchDataFromServer(); // 假设这个请求要3秒console.log(data); // 这行代码要傻等3秒才能执行doSomethingElse(); // 更要再等

所以JavaScript采用异步非阻塞的方式处理这类操作: 发起请求后不干等着, 而是继续执行后面的代码, 等请求完成后再来处理结果. 这就引出了我们最原始的处理方式——回调函数.

 二、回调函数的时代1) 基础回调: 

// 最简单的回调示例function fetchData(callback) {  setTimeout(() => {    callback('数据到手啦!');  }, 1000);}
fetchData((data) => {  console.log(data); // 1秒后输出"数据到手啦!"});

2) 回调地狱: 当多个异步操作需要顺序执行时, 代码就会变成这样: 

// 经典回调地狱getUserInfo(userId, function(user) {  getOrders(user.id, function(orders) {    getOrderDetails(orders[0].id, function(details) {      getProductInfo(details.productId, function(product) {        console.log('最终结果:', product);      });    });  });});

这种代码的问题: 

1. 难以阅读和维护(金字塔形状)

2. 错误处理非常麻烦(要在每个回调里处理错误)

3. 无法使用return和throw

4. 无法使用for循环和try/catch

3) 回调的改进尝试

2.1 命名函数, 把匿名回调变成命名函数:

getUserInfo(userId, handleUser);
function handleUser(user) {  getOrders(user.id, handleOrders);}
function handleOrders(orders) {  getOrderDetails(orders[0].id, handleDetails);}// ...虽然可读性好点了,但代码跳来跳去更晕了

2.2 Async.js库, 提供series/parallel/waterfall等流程控制: 

async.waterfall([  function getUser(callback) {    getUserInfo(userId, callback);  },  function getOrders(user, callback) {    getOrders(user.id, callback);  }  // ...], function finalHandler(err, result) {  // 最终处理});

这些方案虽然有一定效果, 但都不够优雅. 直到Promise的出现. 

三、Promise

3.1 Promise直译就是"承诺", 它表示一个异步操作的最终完成或失败. Promise有三种状态: 

1. pending(进行中)

2. fulfilled(已成功)

3. rejected(已失败)

一旦状态改变就不会再变(要么成功要么失败).

const promise = new Promise((resolve, reject) => {  // 异步操作  setTimeout(() => {    if (Math.random() > 0.5) {      resolve('成功数据');    } else {      reject(new Error('失败原因'));    }  }, 1000);});
promise  .then(data => {    console.log('成功:', data);  })  .catch(err => {    console.error('失败:', err);  });

3.2 Promise链式调用, 这是Promise最强大的地方: 

// 用Promise改造回调地狱getUserInfo(userId)  .then(user => getOrders(user.id))  .then(orders => getOrderDetails(orders[0].id))  .then(details => getProductInfo(details.productId))  .then(product => {    console.log('最终结果:', product);  })  .catch(err => {    console.error('出错啦:', err);  });

对比之前的回调地狱, 这种链式调用: 

1. 扁平化, 可读性极佳

2. 错误处理统一(一个catch处理所有错误)

3. 可以使用return传递数据

4. 可以在then里throw error

3.3 Promise的静态方法: Promise.all: 等所有Promise都成功. 

Promise.all([promise1, promise2, promise3])  .then(([result1, result2, result3]) => {    // 所有都成功才会到这里  })  .catch(err => {    // 任意一个失败就到这里  });

Promise.race:竞速, 第一个完成的Promise决定结果. 

Promise.race([fetchFromA(), fetchFromB()])  .then(firstResult => {    // 使用最先返回的结果  });

Promise.allSettled: 等所有Promise都完成(无论成功失败).

Promise.allSettled([promise1, promise2])  .then(results => {    results.forEach(result => {      if (result.status === 'fulfilled') {        console.log('成功:', result.value);      } else {        console.log('失败:', result.reason);      }    });  });

3.4 Promise的局限性

虽然Promise很棒, 但还是有不足: 

1. 无法取消Promise.

2. 错误处理虽然比回调好, 但还是要用catch.

3. 多个Promise之间的数据共享不太方便.

4. 调试时堆栈信息不友好.

四、aysnc/awaitasync/await是现代JavaScript异步编程的终极解决方案, 它让异步代码看起来和同步代码一样直观, 用起来更简单: 

async function fetchData() {  try {    const user = await getUserInfo(userId);    const orders = await getOrders(user.id);    const details = await getOrderDetails(orders[0].id);    console.log(details);  } catch (err) {    console.error(err);  }}

这代码看起来完全是同步的风格, 但实际上是异步执行的!4.1 async/await函数的特征总是返回Promise:

1) 如果返回非Promise值, 会自动包装成Promise.resolve(值)

2) 如果抛出异常, 返回Promise.reject(异常)

await只能在async函数中使用:

1) 普通函数中使用会报语法错误

2) 现代浏览器和Node.js的模块系统中支持顶层await

4.2 await解析

4.2.1 await的行为

async function example() {  const result = await somePromise;  console.log(result);}

这段代码实际上做了以下几件事:

1. 暂停example函数的执行

2. 等待somePromise完成

3. 如果Promise成功, 恢复执行并将结果赋值给result

4. 如果Promise失败, 抛出拒绝原因(可以用try/catch捕获)

4.2.2 await不一定要等Promise

虽然设计初衷是处理Promise, 但await可以等待任何值:

async function foo() {  const a = await 42; // 等价于 await Promise.resolve(42)  const b = await someFunction(); // 如果someFunction返回非Promise,也会自动包装}

4.2.3 错误处理机制

await的错误处理非常符合直觉, 可以用传统的try/catch: 

async function fetchData() {  try {    const data = await fetch('/api');    const json = await data.json();    console.log(json);  } catch (err) {    console.error('请求失败:', err);  }}

对比Promise的.catch(), 这种写法更接近同步代码的思维模式. 

五、常见使用方式

5.1 顺序执行: 

async function sequential() {  const user = await getUser();  const posts = await getPosts(user.id);  const comments = await getComments(posts[0].id);  return comments;}

5.2 并行执行: 

async function parallel() {  const [user, posts] = await Promise.all([    getUser(),    getPosts()  ]);  return { user, posts };}

5.3 循环中的await: 

// 顺序处理数组async function processArray(array) {  for (const item of array) {    await processItem(item);  }}
// 并行处理数组async function processArrayParallel(array) {  await Promise.all(array.map(item => processItem(item)));}

5.4 await可以等待任何thenable对象: 

async function example() {  const result = await {    then(resolve) {      setTimeout(() => resolve('done'), 1000);    }  };  console.log(result); // 1秒后输出'done'}

5.5 混合使用Promise和async/await: 

async function getUserPosts(userId) {  return fetchUser(userId)  // 返回Promise    .then(user => fetchPosts(user.id))    .then(posts => {      return asyncFunction(posts); // 在then中调用async函数    });}