JavaScript异步编程的演进 - JavaScript学习系列文章

发布时间:2026/8/25 11:55:06

JavaScript异步编程的演进 - JavaScript学习系列文章
一、 为什么需要异步编程先说说为什么要有异步这回事. JavaScript是单线程的, 也就是说它一次只能做一件事. 如果所有操作都同步执行, 遇到网络请求或者文件读取这种耗时的操作, 页面就会卡住不动, 用户体验直接爆炸.// 同步代码的灾难现场constdata fetchDataFromServer();// 假设这个请求要3秒console.log(data);// 这行代码要傻等3秒才能执行doSomethingElse();// 更要再等所以JavaScript采用异步非阻塞的方式处理这类操作: 发起请求后不干等着, 而是继续执行后面的代码, 等请求完成后再来处理结果. 这就引出了我们最原始的处理方式——回调函数.二、回调函数的时代1) 基础回调:// 最简单的回调示例functionfetchData(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和throw4. 无法使用for循环和try/catch3) 回调的改进尝试2.1 命名函数, 把匿名回调变成命名函数:getUserInfo(userId, handleUser);functionhandleUser(user) {getOrders(user.id, handleOrders);}functionhandleOrders(orders) {getOrderDetails(orders[0].id, handleDetails);}// ...虽然可读性好点了但代码跳来跳去更晕了2.2 Async.js库, 提供series/parallel/waterfall等流程控制:async.waterfall([functiongetUser(callback) {getUserInfo(userId, callback);},functiongetOrders(user, callback) {getOrders(user.id, callback);}// ...],functionfinalHandler(err, result) {// 最终处理});这些方案虽然有一定效果, 但都不够优雅. 直到Promise的出现.三、Promise3.1 Promise直译就是承诺, 它表示一个异步操作的最终完成或失败. Promise有三种状态:1. pending(进行中)2. fulfilled(已成功)3. rejected(已失败)一旦状态改变就不会再变(要么成功要么失败).const promise newPromise((resolve, reject) {// 异步操作setTimeout(() {if (Math.random() 0.5) {resolve(成功数据);}else {reject(newError(失败原因));}},1000);});promise.then(data {console.log(成功:, data);}).catch(err {console.error(失败:, err);});3.2 Promise链式调用, 这是Promise最强大的地方:// 用Promise改造回调地狱getUserInfo(userId).then(usergetOrders(user.id)).then(ordersgetOrderDetails(orders[0].id)).then(detailsgetProductInfo(details.productId)).then(product {console.log(最终结果:, product);}).catch(err {console.error(出错啦:, err);});对比之前的回调地狱, 这种链式调用:1. 扁平化, 可读性极佳2. 错误处理统一(一个catch处理所有错误)3. 可以使用return传递数据4. 可以在then里throw error3.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异步编程的终极解决方案, 它让异步代码看起来和同步代码一样直观, 用起来更简单:asyncfunctionfetchData() {try {const user awaitgetUserInfo(userId);const orders awaitgetOrders(user.id);const details awaitgetOrderDetails(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的模块系统中支持顶层await4.2 await解析4.2.1 await的行为asyncfunctionexample() {const result await somePromise;console.log(result);}这段代码实际上做了以下几件事:1. 暂停example函数的执行2. 等待somePromise完成3. 如果Promise成功, 恢复执行并将结果赋值给result4. 如果Promise失败, 抛出拒绝原因(可以用try/catch捕获)4.2.2 await不一定要等Promise虽然设计初衷是处理Promise, 但await可以等待任何值:asyncfunctionfoo() {const a await42;// 等价于 await Promise.resolve(42)const b awaitsomeFunction();// 如果someFunction返回非Promise也会自动包装}4.2.3 错误处理机制await的错误处理非常符合直觉, 可以用传统的try/catch:asyncfunctionfetchData() {try {const data awaitfetch(/api);const json await data.json();console.log(json);}catch (err) {console.error(请求失败:, err);}}对比Promise的.catch(), 这种写法更接近同步代码的思维模式.五、常见使用方式5.1 顺序执行:asyncfunctionsequential() {const user awaitgetUser();const posts awaitgetPosts(user.id);const comments awaitgetComments(posts[0].id);return comments;}5.2 并行执行:asyncfunctionparallel() {const [user, posts] awaitPromise.all([getUser(),getPosts()]);return { user, posts };}5.3 循环中的await:// 顺序处理数组asyncfunctionprocessArray(array) {for (const itemof array) {awaitprocessItem(item);}}// 并行处理数组asyncfunctionprocessArrayParallel(array) {awaitPromise.all(array.map(itemprocessItem(item)));}5.4 await可以等待任何thenable对象:asyncfunctionexample() {const result await {then(resolve) {setTimeout(() resolve(done),1000);}};console.log(result);// 1秒后输出done}5.5 混合使用Promise和async/await:asyncfunctiongetUserPosts(userId) {returnfetchUser(userId)// 返回Promise.then(userfetchPosts(user.id)).then(posts {returnasyncFunction(posts);// 在then中调用async函数});}

相关新闻

JavaScript 中的原型与继承 - JavaScript学习系列文章

JavaScript 中的原型与继承 - JavaScript学习系列文章

2026/8/25 11:55:06

一、从对象说起, 一切皆对象 在 JS 中, 几乎所有的东西都是对象, 或者说最终都会指向某个对象. 比如: let arr [1, 2, 3];console.log(typeof arr); //"object"function foo() {}console.log(typeof foo); //"function" (但本质上也是对象) 简单的对象创建…

开源考试系统本地部署实战:从环境配置到联调排坑全指南

开源考试系统本地部署实战:从环境配置到联调排坑全指南

2026/8/25 11:55:06

1. 项目缘起:为什么要在本地折腾一个开源考试系统?如果你是一名开发者、教育技术从业者,或者是一个小团队的负责人,想搭建一个在线考试平台,大概率会先想到去网上找现成的开源项目。这个想法很对,毕竟从头造…

Python标准库:开箱即用的生产级工具箱与工程实践指南

Python标准库:开箱即用的生产级工具箱与工程实践指南

2026/8/25 11:45:06

1. 什么是Python标准库:不是“第三方”,而是你装完Python就自带的“出厂配置” 很多人第一次听说“Python标准库”,下意识会把它和pip install安装的requests、numpy、pandas混为一谈——这其实是个根本性误解。Python标准库(Pyt…

Python从零到一:基础语法趣味入门指南

Python从零到一:基础语法趣味入门指南

2026/8/25 12:35:08

在当前 AI 大环境下,Python 语言在编程语言中的比重大幅增长,学习 Python 语言已经成为做 AI 应用开发的重要前置条件。学习 Python 语言就从此刻开始,随我来一起学习了解一下它吧。本文从 Python 语言的基础语法使用开始介绍,逐步…

零基础搭建《我的世界》基岩版私人服务器:从局域网到公网联机全攻略

零基础搭建《我的世界》基岩版私人服务器:从局域网到公网联机全攻略

2026/8/25 12:35:08

想和三五好友一起在《我的世界》基岩版里建造、冒险,却苦于找不到稳定、免费的服务器?或者觉得租用服务器太麻烦、太贵?其实,你完全可以用自己的电脑搭建一个专属的私人服务器!无论是宿舍局域网,还是天南海…

零成本搭建《我的世界》基岩版服务器:从本地部署到外网联机全攻略

零成本搭建《我的世界》基岩版服务器:从本地部署到外网联机全攻略

2026/8/25 12:35:08

这次我们来看一个非常实际的需求:如何在自己的电脑上搭建一个《我的世界》基岩版服务器,实现和朋友联机。很多玩家想和朋友一起玩,但不想租用昂贵的服务器,或者只是想临时开个服体验一下。其实,用你自己的电脑就能搞定…

数据加解密基础知识

数据加解密基础知识

2026/8/25 12:35:08

文章目录数据加解密基础知识笔记为什么要做数据加解密几个必须区分的基础概念加密算法的三大分类对称加密什么是对称加密常见对称加密算法对称加密的优点对称加密的缺点常见使用场景非对称加密什么是非对称加密常见非对称加密算法非对称加密的优点非对称加密的缺点常见使用场景…

仓储货架对楼面载荷怎么算?一个公式搞定(附计算实例)

仓储货架对楼面载荷怎么算?一个公式搞定(附计算实例)

2026/8/25 12:35:08

仓储货架对楼面载荷怎么算?一个公式搞定(附计算实例) 文章目录仓储货架对楼面载荷怎么算?一个公式搞定(附计算实例)前言一、先搞清楚两个概念:平均载荷 vs 集中载荷二、立柱集中载荷计算公式三、…

基于AI大模型的JSON文件高质量汉化实战:告别垃圾机翻

基于AI大模型的JSON文件高质量汉化实战:告别垃圾机翻

2026/8/25 12:25:08

大家好,我是专注于分享实用开发技巧的技术博主。在日常开发或使用各类软件、工具时,我们经常会遇到需要汉化 JSON 配置文件、语言包或插件的情况。传统的汉化工具(如一些自动化脚本或早期工具)往往依赖简单的机器翻译,…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/24 19:53:32

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/24 19:56:07

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/24 21:16:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

2026/8/25 0:04:34

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

2026/8/25 0:04:35

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

2026/8/25 0:04:35

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG 【免费下载链接】transformers.js State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server! 项目地址: https:/…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…