啥是Promise
官方解释
Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。 promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态) ;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
听不懂对不对!
通俗解释
就是你给你暗恋女神发信息告白(创建了一个Promise),接着你就等她回信息了(进入pending状态),等她回信息的过程你很焦虑啊,为了缓解焦虑你去超时捏泡面(异步的操作),最后女神给你回信息了,有两种情况:一、女神答应你啦(fulfiled成功态)二、女神狠狠的拒绝你了(rejected失败态)。但是不管啥情况都没办法再改变女神的决定,这就是Promise!
好啦,解释完Promise那我们来说说Promise能干啥。
能干啥?先说答案!解决地狱回调
哦哦哦~原来Promise是用来解决地狱回调啊,那。。。啥是地狱回调?
比如:我周六想去打篮球,但是我能不能去取决于女朋友约不约我逛街,但是我女朋友约不约我逛街又取决于她闺蜜找不找她,那么我们写成代码应该这样写
function func(res, callback) {
if (res) {
callback()
} else {
console.log('兄弟们,我不能去打球了')
}
}
let playBasketball = function () {
// 闺蜜不找女朋友逛街了
func(true, function () {
// 女朋友决定找我逛街了
func(true, function () {
// 我要打电话给兄弟们说我不能去打球了
func(false)
})
})
}
playBasketball()
这种层层嵌套的代码就叫地狱回调,代码耦合性强,一旦一个环节出错就会原地爆炸
那么用Promise怎么来写呢
let func = function (res) {
return new Promise((resolve, reject) => {
if (res) {
resolve()
} else {
reject('兄弟们,我不能去打球了')
}
})
}
func(true)
// 闺蜜不找女朋友逛街了
.then(() => {
return func(true)
})
// 女朋友决定找我逛街了
.then(() => {
return func(false)
})
// 我要打电话给兄弟们说我不能去打球了
.catch((err) => {
console.log(err)
})
是不是清楚多了!就算其中一步错了也很好修改和维护。
基本用法
介绍完什么是Promise和Promise为了解决什么问题,那么接下来说一说Promise的基本用法
首先Promise是个构造函数,如果你要用,那你就new一个
从上面的例子中可以看到Promise构造函数中包含resolve和reject两个参数
- resolve :异步操作执行成功后的回调函数
- reject:异步操作执行失败后的回调函数
那么我们来通俗解释一下。回到刚开始我们跟女神表白的例子。
如果女神答应我了就执行resolve,如果女神拒绝我了就执行reject。懂了么?票们!
.then方法
Promise会有个.then的方法,这也是Promise的核心,.then返回的是一个新的Promise,因此可以使用链式写法,就像上面的那段代码一样,如果你想,可以一直.then下去。
.then方法可以接收两个回调函数作为参数
第一个回调函数是Promise决议为成功时执行的,第二个回调函数是Promise决议为失败时执行的。啥意思?上代码!
let love = function (msg) {
return new Promise((resolve, reject) => {
if (msg) {
// 如果女神答应我,我就去跟她约会
resolve('我们约会吧')
} else {
// 如果女神拒绝我,我就去超市捏泡面
reject('去超市捏泡面')
}
})
}
love(true).then(res => {
console.log(res)
}, err => {
console.log(err)
})
如上,因为传值是true,所以打印出的是‘我们约会吧’,如果传值是false,相应打印出的就是‘去超市捏泡面’
.catch方法
这个方法就好理解了,名如其名,就是用来捕获错误的。就是说如果Promise决议为失败了,但是.then又没有处理那么就会被.catch捕获,又因为.then也返回Promise所以.then中的错误也会被.catch捕获。
所以一般我们最后都会加上.catch方法。画个小重点,.catch一样返回Promise,所以一样可以接着调用.then
.finally方法
兄弟们,咱就是这么说吧,如果.then和.catch你搞懂了,这个finally对你来说简直不在话下。
啥意思呢,还是名如其名,就是不管.then和.catch执行多少次,那么最后都得来执行下.finally。所以.finally一定是放在最后的。
你要问我有啥用?我来给你举个栗子
业务场景中经常有发送请求弹出loading等待的提示,但是有的请求是成功的,有的是失败的,咱不能在.then和.catch都加个关闭loading的操作吧,这么low的操作也不像咱们的风格,那.finally就排上用场了。
话不多说,上才艺
let func = function (msg) {
return new Promise((resolve, reject) => {
window.setTimeout(() => {
if (msg) {
resolve('成功')
} else {
reject('失败')
}
}, 1000)
})
}
func(true)
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
.finally(() => {
console.log('关闭loading')
})
可以看到不管是成功还是失败最终都打印出了‘关闭loading’。
.all方法
.all方法就是把多个Promise组合成一个新的Promise实例。所以它接收的参数就是一个数组。返回的是一个新的Promise。
Promise.all方法必须要传入的Promise都变为fulfilled的时候它才会为fulfilled,只要有一个为rejected的时候它就变为rejected。一家人要整整齐齐的么
let Promise1 = new Promise((resolve, reject)=>{})
let Promise2 = new Promise((resolve, reject)=>{})
let Promise3 = new Promise((resolve, reject)=>{})
let p = Promise.all([Promise1, Promise2, Promise3])
p.then(funciton(){
// 三个都成功则成功
}, function(){
// 只要有失败,则失败
})
当有多个异步请求的时候咱们就可以用Promise.all来等待所有异步请求都结束后再执行操作。
.race方法
咱们再来说说这个用的很少的东东race。这个跟.all很像,也是接收多个Promise作为参数,也是返回一个新的Promise,区别在哪呢?咱们谷歌翻译一下race有竞赛的意思,也就是说传入的参数中,哪个最先改变状态,那.race就会跟着改变。也就是说谁跑的快听谁的。
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是小明')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('我是小黄')
}, 500)
})
let p3 = Promise.resolve('我是小毛')
let result = Promise.race([p1, p2, p3])
// 状态就是fulfilled,并且值就是‘我是小毛’
console.log(result)
好啦,Promise大概就是这么多东西,相信不是太难理解,大家加油哦!