深入了解Promise对象,写出优雅的回调代码,告别回调地狱
深入浅出了解Promise
引言
我们都知道,一个好的代码是有很强的维护性、阅读性的, 但是在Jacascript中的回调函数的量一增多, 很容易影响代码的阅读性,导致代码难以维护, 这种现象就叫做回调地狱, 为了解决这现象, ES6将Promise写进了语言标准里, 专门用来解决这个回调地狱的现象, 那么就让我们来了解一下吧。
正文
一、Promise简介
Promise 是异步编程的一种解决方案, 他能使得各种异步操作,都用同样的方式去处理, 将代码变得非常的统一, 使得维护和阅读都便利了很多, 我们现在简单看一下, 不用Promise时,回调函数的数量很多的时候的代码,以及使用Promise以后的代码吧。
- 不使用Promise
$.ajax({
url: '/index',
type: 'get',
dataType: 'json',
success: function (data1) {
$.ajax({
url: '/home',
type: 'get',
dataType: 'json',
data: data1,
success: function (data2) {
$.ajax({
url: '/about',
type: 'get',
dataType: 'json',
data: data2,
success: function (data3) {
$.ajax({
url: '/me',
type: 'get',
dataType: 'json',
data: data3,
success: function (data4) {
console.log(data4)
}
})
}
})
}
})
}
})
- 使用Promise
new Promise(resolve => {
$.ajax({
url: '/index',
type: 'get',
dataType: 'json',
success: function (data1) {
resolve(data1)
}
})
})
.then(data1 => {
$.ajax({
url: '/home',
type: 'get',
dataType: 'json',
data: data1,
success: function (data2) {
resolve(data2)
}
})
})
.then(data2 => {
$.ajax({
url: '/about',
type: 'get',
dataType: 'json',
data: data2,
success: function (data3) {
resolve(data3)
}
})
})
.then(data3 => {
$.ajax({
url: '/index',
type: 'get',
dataType: 'json',
data: data3,
success: function (data4) {
console.log(data4)
}
})
})
使用或不使用Promise, 这区别已经很明显了吧, 显而易见,使用完Promise后, 这种回调函数里面嵌套回调函数的代码就变得很简洁,耐看,那我们就开始学习Promise的使用吧
二、Promise的三种状态
- pending: 等待状态,比如正在网络请求, 或定时器没有到时间
- fulfill: 满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调then函数
- reject: 拒绝状态,当我们主动回调了reject时 , 就处于该状态,并且会回调catch函数
三、函数then( )
函数 then 是Promise中的一个方法, 它会在Promise 处于 fulfill 状态时调用触发。
resolve 和 reject 是默认传入的的函数参数
new Promise((resolve, reject) => {
setTimeout(() => {
//在Promise调用resolve函数,会使Promise变为 fulfill状态
//resolve函数可以传入一个参数,作为then函数的默认传入参数
resolve('成功')
}, 1000)
})
.then(data => {
console.log(data)
})
//结果输出: 成功
四、函数catch( )
函数 catch 是Promise中的一个方法, 它会在Promise 处于 reject 状态时调用触发。
new Promise((resolve, reject) => {
setTimeout(() => {
//在Promise调用reject函数,会使Promise变为 reject 状态
//reject函数可以传入一个参数,作为catch函数的默认传入参数
reject('失败')
}, 1000)
})
.catch(err => {
console.log(err)
})
//结果输出: 失败
五、函数finally( )
函数 finally 是Promise中的一个方法, 它会在Promise 的最后触发,无论Promise处于什么状态。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功啦')
}, 1000)
})
.then(data => {
console.log(data)
})
.finally(() => {
console.log('Promise结束')
})
/*结果输出: 成功啦
Promise结束
*/
new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败')
}, 1000)
})
.catch(err => {
console.log(err)
})
.finally(() => {
console.log('Promise结束')
})
/*结果输出: 失败
Promise结束
*/
可以看到,无论Promise是处于 fulfill 状态 ,还是 reject 状态, 最终都会执行finally函数
六、函数all( )
函数 all 是Promise 中的一个方法,他用于将多个Promise 实例, 包装成一个新的Promise 实例
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是第一个异步请求返回的数据')
},3000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是第二个异步请求返回的数据')
},1000)
})
])
.then(results => {
console.log(results)
})
// ['我是第一个异步请求返回的数据', '我是第二个异步请求返回的数据']
上述代码中, all 函数传入一个数组,数组中的每个元素都是一个Promise实例, 只有当数组中的每个Promise实例都处于 fulfill 状态时,才会调用外部新包装成的Promise 的 then方法, 并且这个 then 方法默认传入一个数组参数,该数组参数中的每个元素为 all 函数中每个实例参数 resolve 传回的数据。
七、实际应用
需求说明: 传入一个字符串 string1 = ’ I am ',然后1秒后,在string1后面加上一个字符串 ’ Lpyexplore ’ , 得到一个新的字符串 string2 = ’ I am Lpyexplore ’ , 然后再过1秒后,在string2 后面加上一个字符串 ’ in CSDN ’ ,得到又一个新的字符串 string3 = ’ I am Lpyexplore in CSDN ’ , 然后打印字符串 string3 , 同时输出打印 ’ Promise结束 ’
let string1 = 'I am '
new Promise((resolve, reject) => {
setTimeout(() => {
let string2 = string1 + 'Lpyexplore '
resolve(string2)
}, 1000)
})
.then(data => {
return new Promise((resolve, reject) => {
let string3 = data + 'in CSDN'
resolve(string3)
})
})
.then(data => {
console.log(data)
})
.finally(() => {
console.log('Promise结束')
})
// 输出结果:
// I am Lpyexplore in CSDN
// Promise结束
结束语
相信大家对Promise都有了一定的了解了吧, 以后可以将多重回调的代码用Promise 来写, 写出优雅耐看的代码,让自己舒心,让领导放心,嘻嘻。
深入了解Promise对象,写出优雅的回调代码,告别回调地狱的更多相关文章
- 如何写出优雅的JavaScript代码 ? && 注释
如何写出优雅的JavaScript代码 ? 之前总结过一篇<如何写出优雅的css代码?>, 但是前一段时间发现自己的js代码写的真的很任性,没有任何的优雅可言,于是这里总结以下写js时应当 ...
- 如何写出优雅的CSS代码 ?(转)
对于同样的项目或者是一个网页,尽管最终每个前端开发工程师都可以实现相同的效果,但是他们所写的代码一定是不同的.有的优雅,看起来清晰易懂,代码具有可拓展性,这样的代码有利于团队合作和后期的维护:而有的混 ...
- 如何写出优雅的css代码 ?
如何写出优雅的css代码 ? 对于同样的项目或者是一个网页,尽管最终每个前端开发工程师都可以实现相同的效果,但是他们所写的代码一定是不同的.有的优雅,看起来清晰易懂,代码具有可拓展性,这样的代码有利于 ...
- 【原创】怎样才能写出优雅的 Java 代码?这篇文章告诉你答案!
本文已经收录自 JavaGuide (59k+ Star):[Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识. 本文比较简短,基本就是推荐一些对于写好代码非常有用的文章或者 ...
- 如何写出优雅的 Golang 代码
原文: https://draveness.me/golang-101.html Go 语言是一门简单.易学的编程语言,对于有编程背景的工程师来说,学习 Go 语言并写出能够运行的代码并不是一件困难的 ...
- 如何写出优雅的Python代码?
有时候你会看到很Cool的Python代码,你惊讶于它的简洁,它的优雅,你不由自主地赞叹:竟然还能这样写.其实,这些优雅的代码都要归功于Python的特性,只要你能掌握这些Pythonic的技巧,你一 ...
- 如何写出优雅兼备可读性的javascript代码
即或是最简单的需求,不同的程序员也会写出不一样的代码: 需求:充值程序过虑不符合条件的充值金额,即只能充入100.200.500.1000金额,其它过虑: 1.菜鸟程序员可能会这样写,虽然可读性强,代 ...
- 如何用java写出无副作用的代码
搞java的同学们可能对无副作用这个概念比较陌生,这是函数式编程中的一个概念,无副作用的意思就是: 一个函数(java里是方法)的多次调用中,只要输入参数的值相同,输出结果的值也必然相同,并且在这个函 ...
- JAVA语言之怎样写出高性能的Java代码?
本文主要向大家介绍了JAVA语言之怎样写出高性能的 Java 代码?通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 在这篇文章中,我们将讨论几个有助于提升Java应用程序性能的方法.我 ...
随机推荐
- AI面试之SVM推导
SVM现在主流的有两个方法.一个是传统的推导,计算支持向量求解的方法,一个是近几年兴起的梯度下降的方法. 梯度下降方法的核心是使用了hinge loss作为损失函数,所以最近也有人提出的深度SVM其实 ...
- Jpa常用注解@Test
/** * 客户的实体类 * @author zhy * * 明确使用的注解都是JPA规范的 * 所以导包都要导入javax.persistence包下的 * */ @Entity//表示当前类是一个 ...
- Zabbix添加监控主机
一.监控server本机 1.查看主机列表 2.启动server主机的zabbix-agent服务 [root@zabbix ~]# systemctl start zabbix-agent.serv ...
- Mysql安装使用教程
一:简介 MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理.MySQL是开放源代码的,因此任何人都可以在Genera ...
- PHP is_finite() 函数
实例 判断一个值是否为有限值: <?phpecho is_finite(2) . "<br>";echo is_finite(log(0)) . "&l ...
- AtCoder Grand Contest 044 A Pay to Win 贪心
LINK:Pay to Win 自闭了 比赛的时候推出来正解了 以为复杂度不对 写完扔了 没拿map存状态就扔了23333... 一个T点:在更新map的时候 >不要写成>= 不然会徒劳的 ...
- 4.19 ABC F path pass i 容斥 树形dp
LINK:path pass i 原本想了一个点分治 yy了半天 发现重复的部分还是很难减掉 况且统计答案的时候有点ex. (点了别人的提交记录 发现dfs就过了 于是yy了一个容斥 发现可以直接减掉 ...
- C语言中的数据转换和定义常量
一.数据转换 1.数据类型转换:C 语言中如果一个表达式中含有不同类型的常量和变量,在计算时,会将它们自动转换为同一种类型:在 C 语言中也可以对数据类型进行强制转换: 2.自动转换规则: a)浮点数 ...
- 使用ProxySQL实现MySQL Group Replication的故障转移、读写分离(一)
导读: 在之前,我们搭建了MySQL组复制集群环境,MySQL组复制集群环境解决了MySQL集群内部的自动故障转移,但是,组复制并没有解决外部业务的故障转移.举个例子,在A.B.C 3台机器上搭建了组 ...
- JVM系列之:从汇编角度分析Volatile
目录 简介 重排序 写的内存屏障 非lock和LazySet 读的性能 总结 简介 Volatile关键字对熟悉java多线程的朋友来说,应该很熟悉了.Volatile是JMM(Java Memory ...