解析 JavaScript 异步编程:从回调地狱到 Promise 和 Async/Await

在这里插入图片描述

在现代的JavaScript开发中,处理异步任务变得愈发重要,因为它们允许我们在等待I/O、网络请求或定时器等事件时继续执行其他任务,以提高程序的性能和响应能力。本文将介绍JavaScript中异步编程的演变过程,从最初的回调地狱到后来的Promise和Async/Await。

回调地狱

回调地狱是一种异步编程的反模式,它在嵌套的回调函数中处理多个异步任务,导致代码难以阅读和维护。以下是一个简单的回调地狱演示:

function add(a: number, b: number, callback: (res: number) => void): void  {setTimeout(() => {callback(a + b);}, 1000);
}// 回调地狱示例
add(2, 3, res => {console.log('2 + 3 = ', res);add(res, 4, res => {console.log('2 + 3 + 4 = ', res);add(res, 5, res => {console.log('2 + 3 + 4 + 5 = ', res);});});
});

如上所示,每个异步任务的结果都在回调函数中处理,形成了嵌套的结构,使得代码难以理解。

Promise

Promise是一种用于处理异步任务的对象,它代表了一个异步操作的最终完成或失败,并提供了更优雅的解决方案,避免了回调地狱的问题。

async function add2(a: number, b: number): Promise<number>  {return new Promise((resolve, reject) => {setTimeout(() => {resolve(a + b);}, 2000);});
}// Promise链式调用
add2(2, 3).then((res: number )=> {console.log('2 + 3 = ', res);return add2(res, 4);}).then((res: number )=>{console.log('2 + 3 + 4 = ', res);return add2(res, 4);}).then((res: number) => {console.log('result:', res);}).catch(e => console.error(`ERROR: ${e}`));

通过Promise,我们可以将异步任务按顺序组织在链式调用中,使得代码更具可读性。

Promise的异常捕获

Promise还提供了异常捕获机制,使得我们可以方便地处理异步任务的错误。

add2(2, 3).then((x: number )=> Promise.reject(10)).then((x: number )=> add2(x, 6)).then((res: number) => console.log(res)).catch(e => console.error(`ERROR: ${e}`));

在这个例子中,当第一个Promise返回了一个拒绝状态时,异常会被捕获,而不会继续执行后续的Promise。

Promise的组合

Promise.all和Promise.race是Promise的两个重要方法。Promise.all等待所有Promise都完成,而Promise.race在第一个Promise完成时就终止。

// Promise同时等待后做事情
Promise.all([add2(2, 3), add2(4, 5)]).then(([a , b]) => {console.log('result', a, b);return mul(a, b);
}).then((res: number) =>console.log('result:', res)
);// Promise谁先做事情就用谁
Promise.race([add2(2, 3), mul(4, 5)]).then((res: number) =>console.log('result:', res)
);

这两个方法使我们能够更灵活地组合和控制多个异步任务的执行。

Async/Await

Async/Await是ES2017引入的异步编程语法糖,使得异步代码更加像同步代码一样,进一步提高了可读性。

async function main(): Promise<void> {try {const result1 = await add2(2, 3);console.log('2 + 3 = ', result1);const result2 = await add2(result1, 4);console.log('2 + 3 + 4 = ', result2);const result3 = await add2(result2, 5);console.log('2 + 3 + 4 + 5 = ', result3);} catch (error) {console.error(`ERROR: ${error}`);}
}main();

使用Async/Await,我们可以更清晰地表达异步任务的执行顺序,避免了回调地狱和过多的Promise链。

总的来说,JavaScript异步编程的演进经历了从回调地狱到Promise和最终的Async/Await的过程,这些新的语法和模式为开发者提供了更强大和清晰的工具,使得异步代码更易于编写和维护。希望本文对你理解JavaScript异步编程有所帮助。

JavaScript异步编程的最新进展:从Promise.allSettled到Promise.any

在ES2020和ES2021中,JavaScript引入了一些新的异步编程方法,进一步改善了处理Promise的体验。本文将介绍其中两个方法:Promise.allSettledPromise.any

Promise.allSettled(ES2020)

在ES2020中,JavaScript引入了 Promise.allSettled 方法,它用于处理多个Promise,无论它们是被解决(fulfilled)还是被拒绝(rejected)。

function asyncFunction1(): Promise<string> {return new Promise(resolve => setTimeout(() => resolve('Result from asyncFunction1'), 1000));
}function asyncFunction2(): Promise<number> {return new Promise(resolve => setTimeout(() => resolve(42), 500));
}// 使用 allSettled 扩展方法
const promises = [asyncFunction1(), asyncFunction2()];Promise.allSettled(promises).then(results => {results.forEach(result => {if (result.status === 'fulfilled') {console.log(`Fulfilled: ${result.value}`);} else {console.log(`Rejected: ${result.reason}`);}});
});

Promise.allSettled 返回一个新的Promise,该Promise在所有传入的Promise都已经被解决或被拒绝后才被解决。它返回一个包含每个Promise结果的对象数组,每个对象都包含 statusvaluereason 属性。

这使得我们能够轻松地处理多个Promise的状态,而不必担心其中一个Promise被拒绝而导致整个操作失败。

Promise.any(ES2021)

在ES2021中,JavaScript引入了 Promise.any 方法,它用于处理多个Promise,只要其中至少有一个被解决。

function asyncFunction3(): Promise<string> {return new Promise(resolve => setTimeout(() => resolve('Result from asyncFunction3'), 1000));
}function asyncFunction4(): Promise<number> {return new Promise((_, reject) => setTimeout(() => reject('Error from asyncFunction4'), 500));
}// 使用 any 扩展方法
const promises2 = [asyncFunction3(), asyncFunction4()];Promise.any(promises2).then(result => {console.log(`Resolved: ${result}`);// 处理至少一个 Promise 被 resolved 的逻辑}).catch(errors => {console.error(`Rejected with all errors: ${errors}`);// 处理所有 Promise 都被 rejected 的逻辑});

Promise.any 返回一个新的Promise,该Promise在传入的Promise中至少有一个被解决后就被解决。它只要有一个Promise被解决,就会返回该Promise的解决值。

这个方法很有用,因为它提供了一种在多个异步任务中找到第一个成功解决的任务的方式。

这两个新方法为JavaScript开发者提供了更多处理异步任务的选择,使得我们能够更灵活地应对各种异步场景。希望这篇文章对你理解Promise.allSettledPromise.any有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/454007.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】交叉验证求光滑因子的广义神经网络回归预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 交叉验证求光滑因子的广义神经网络回归预测算法是一种用于选择模型超参数并提高泛化性能的方法。下面将对该算法进行详细介绍&#xff1a; 广义神经网络回归模型&#xff1a; 广义神经网络…

黑豹程序员-ElementPlus支持树型组件带图标以及icon避坑

效果 vue代码 参数说明&#xff1a;node当前节点&#xff0c;data当前节点后台传入数据。 el-tree自身不支持图标&#xff0c;需要自己去利于实现&#xff0c;并有个坑&#xff0c;和elementui写法不同。 <el-col :span"12"><el-form-item label"绑定…

docker-compose部署laravel项目实战(主机nginx连接项目容器)(详细配置过程)

我用的是主机上的nginx,没有用docker安装nginx&#xff0c; 所以需要先在主机上安装nginx # 更新系统yum sudo yum update# 安装安装包sudo yum install epel-release sudo yum install wget# 安装Nginx sudo yum install nginx #启动 sudo systemctl start nginx #开机自启动…

3D Line Mapping Revisited论文阅读

1. 代码地址 GitHub - cvg/limap: A toolbox for mapping and localization with line features. 2. 项目主页 3D Line Mapping Revisited 3. 摘要 提出了一种基于线的重建算法&#xff0c;Limap&#xff0c;可以从多视图图像中构建3D线地图&#xff0c;通过线三角化、精心…

SAP SHDB VLPOD 录屏带序列号的

考虑到交货单有多种情况 1个行项目 多个数量,需要对应多个序列号 多个行项目,多个数量,需要多个序列号 最终形成的FM如下 FUNCTION ZIF_BDC_VLPOD_RE_S. *"---------------------------------------------------------------------- *"*"本地接口: *…

人脸识别基本流程

人脸识别一般包括&#xff1a;人脸检测、人脸对齐、人脸特征提取和人脸比对四个步骤 人脸检测&#xff1a;检测到人脸的位置人脸对齐&#xff1a;同一个人采集到的不同图像可能呈现出不同的姿态和表情等&#xff0c;这种情况是不利于人脸特征提取的。所以有必要将人脸图像都变…

【go】延迟执行和定时器实现

目录 time.Sleep time.After time.NewTimer time.NewTicker time.Sleep time.Sleep可以实现延时执行 func TestSleep(t *testing.T) {fmt.Println("start time:", time.Now().Format("2006-01-02 15:04:05.000"))time.Sleep(2 * time.Second)fmt.Pri…

网站不收录,与服务器不备案有关吗

随着互联网的快速发展&#xff0c;网站已经成为企业、个人和机构宣传和展示自己的重要平台。然而&#xff0c;许多网站在建设完成后却面临着不收录的问题&#xff0c;这给网站的管理者和拥有者带来了很大的困扰。其中&#xff0c;一些人认为&#xff0c;网站不收录的原因与服务…

2024美赛数学建模C题完整论文教学(含十几个处理后数据表格及python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了数学建模美赛本次C题目Momentum in Tennis完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文。 C论文共49页&…

网络原理TCP/IP(5)

文章目录 IP协议IP协议报头地址管理网段划分特殊的IP地址路由选择以太网认识MAC地址对比理解MAC地址和IP地址DNS&#xff08;域名服务器&#xff09; IP协议 IP协议主要完成的工作是两方面&#xff1a; 地址管理&#xff0c;使用一套地址体系&#xff0c;来描述互联网上每个设…

群晖各个型号之间有什么特色和区别

https://www.mi-d.cn/1338 您可以通过编译不同的型号固件来实现你想要的功能特性 DS3622xs、DS3617xs、SA6400 DSM7.x版本开始都支持24个CPU线程&#xff0c;其它的大部分型号都最多只支持8个线程&#xff08;DS918、DS920&#xff09;或16个线程&#xff0c;如果你的CPU核心…

JAVA Web 学习(五)Nginx、RPC、JWT

十二、反向代理服务器——Nginx 支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量&#xff0c;其占用内存少、并发能力强、能支持…