前言
在项目中,使用了很多此 Promise
,然而它到底是怎样的呢?
在学习 Promise
之前,我们来看看下面这几道题:
它们打印的结果到底是什么呢?
别急,我们先来了解一下 Promise
的基本用法
一、三种状态
我们先从状态开始,Promise
有三种状态,它们分别是
pending
—— 初始状态,既不是成功,也不是失败状态fulfilled
—— 操作成功完成状态rejected
—— 操作失败状态
现在让我们来看看这三种状态会在什么时候触发呢?首先我们来写一个简单的 Promise
,并在浏览器中打印它的返回值(这里解释下,promise
会默认返回 promise
对象)
const p1 = new Promise((resolve, reject) => {})
console.log('p1', p1)
此时在浏览器中查看打印结果,会发现,它是 pending
状态
那我们再来做个小实验,在 Promise
中,将 resolve
回调函数放入 setTimeout
并在 10 秒后再次打印 Promise
,看看打印结果会是什么样呢
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 10)
})
setTimeout(() => {console.log('p2-setTimeout', p2)}, 10)
此时,在浏览器中查看打印结果,会发现它从pending
状态变成了 fulfilled
的状态
接下来我们就来对第三种状态做个小小的实验,方法与第二种状态一致,只是换了个回调函数执行:
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject()
}, 10)
})
console.log('p3', p3)
setTimeout(() => {console.log('p3-setTimeout', p3)})
此时,我们在浏览器中查看它的打印结果:
会发现此时 Promise
的状态从pending
状态变成了 rejected
的状态
综合以上三个小实验,我们已经明白了 Promise
状态从 pending
状态到 fulfilled
/rejected
状态的一个变化过程。
那么接下来,我们就来看看,它这三种状态的变化到底是怎么样的呢?
二、状态的变化
![2780f33e033716ffa01a5be6e599c9ec.png](https://i-blog.csdnimg.cn/blog_migrate/c6ce3c9e0e7f01346d5187d0ca459e59.png)
根据打印结果,我们可以得知 Promise
原型上有三个方法:
catch(onRejected)
then(onFulfilled, onRejected)
finally(onFinally)
现在我们根据小栗子? 来看看,什么时候会触发这三个原型方法。
pending 状态
我们创建一个 Promise
const p1 = new Promise((resolve, reject) => {})
console.log('p1', p1)
p1.then(res => {
console.log(1)
}).catch(err => {
console.log(err)
}).finally(() => {
console.log(2)
})
从上面代码我们可以得知:当打印 p1
时,p1
为 pending
状态(在第一个例子中就已经说明了此时的 Promise
是 pending
状态哦)
我们知道 pending
是初始状态,既不是成功,也不是失败状态,它是否会触发 then
、catch
、finally
回调呢?
现在我们就来验证一下,打开浏览器查看一下打印结果:
发现,此时只打印了 p1
,并没有触发 then
、catch
、finally
任何一个回调,由此,我们可以得出一个结论:
pending
状态不会触发 then
、catch
、finally
fulfilled 状态
那我们再来做个小实验,在 Promise
中,触发 resolve
回调函数,看看打印结果会是什么样呢
const p1 = new Promise((resolve, reject) => {
resolve('我是成功完成状态')
})
console.log('p1', p1)
p1.then(res => {
console.log('then 回调触发: ', res)
}).catch(err => {
console.log('catch 回调触发: ',err)
}).finally(() => {
console.log('finally 回调触发')
})
从上面代码我们可以得知:当打印 p1
时,p1
为 fulfilled
状态(在第一个例子中就已经说明了此时的 Promise
是 fulfilled
状态哦)
我们知道 fulfilled
是操作成功完成状态,那么它是否会触发 then
、catch
、finally
回调呢?
我们来看看打印结果:
从打印结果来看,此时触发了 then
和 finally
回调,并且括号中的东西会传入到 then
回调函数中由此,我们可以得出一个结论:
fulfilled
状态会触发后续的 then
和 finally
回调函数
rejected 状态
经过之前的例子,我们现在来创建一个 Promise
,并触发 reject
回调函数:
const p1 = new Promise((resolve, reject) => {
reject('我是操作失败状态')
})
console.log('p1', p1)
p1.then(res => {
console.log('then 回调触发: ', res)
}).catch(err => {
console.log('catch 回调触发: ',err)
}).finally(() => {
console.log('finally 回调触发')
})
由之前的小实验可以知道这时的 p1
是 rejected
状态 —— 操作失败状态,当 Promise
为 pending
时,什么都不触发,当 Promise
为 fulfilled
时,会触发 then
和 finally
回调函数。
那么当它为 rejected
时,会触发什么回调函数呢?
让我们来康康 ? :
可以看到,当 Promise
为 rejected
状态时,它也会触发 finally
回调函数,但是它会触发 catch
回调函数,不会触发 then
回调函数,并且括号中的东西会传入到 catch
回调函数中。由此,我们可以得出一个结论:
rejected
状态会触发后续的 catch
回调函数
到这里,我们已经对 Promise
的三种状态有所了解了,那接下来,我们就来看一看,这三种状态遇到非正常情况下,会出现什么样的结果呢?
三、then 和 catch 对状态的影响
ps: 这里可能会比较晕,但是别着急,一步一步来,到了后面你就会茅塞顿开
3.1 then 对状态的影响
首先我们新建一个 fulfilled
状态的 Promise
const p1 = Promise.resolve().then(() => {
return 100
})
console.log('p1', p1)
p1.then(() => {
console.log('123')
})
打开浏览器可见 promise
的状态是 fulfilled
,并且此时触发了 then
回调
当然,上面的例子我们不用运行肯定也知道打印结果,那么如果我们在 then
中抛出一个错误,猜猜它会触发什么回调呢?
const p2 = Promise.resolve().then(() => {
throw new Error('error')
})
console.log('p2', p2)
p2.then(() => {
console.log('456')
}).catch((err) => {
console.log('error', err)
})
看看上面?的代码,脑补一下,此时的打印结果会是什么
现在我们在浏览器中查看打印结果:
从打印结果来看,p2
并没有触发 then
回调,而是直接触发了 catch
回调
因此,我们可以得出一个结论:
then
正常返回 fulfilled
,里面有报错则返回 rejected
3.2 catch 对状态的影响
我们已经模拟了 then
对状态的影响,那么接下来,我们来看看 catch
对状态有什么影响呢?
既然是观察 catch
,那我们就来创建一个 rejected
的 Promise
吧
const p3 = Promise.reject('my error').catch((err => {
console.log('err', err)
}))
console.log('p3', p3)
p3.then(() => {
console.log('then', 100)
})
现在我们来猜猜这段代码的打印结果是什么?在脑袋里悄悄运行下~
让我们打开浏览器查看打印结果,验证一下是不是跟自己运行的一致呢?
从打印结果来看,Promise
返回了一个 fulfilled
的 Promise
,我们回想一下,fufilled
是操作成功完成状态 状态的 Promise
,也就是上面?的总结 —— then
、catch
、finally
这三个方法都会返回一个新的 Promise
对象。
那我们现在再来看个小栗子?
const p4 = Promise.reject('my error').catch((err => {
throw new Error('p4 error')
}))
console.log('p4', p4)
p4.then(() => {
console.log(200)
}).catch((err) => {
console.log('catch err', err)
}).then(() => {
console.log(500)
throw new Error('error1')
}).catch(() => {
console.log(600)
})
我们在脑海里运行一下,上面这段代码的打印结果是什么(先不要看结果哦~)
好了,现在我们来验证一下,看看我们自己运行的结果是否与浏览器一致呢
由结果可知:当 Promise
的状态为 rejected
时,会触发 catch
回调(这是毋庸置疑的),执行完 catch
回调时,正常情况下,catch
回调会返回 fufilled
状态的 Promise
,当 catch
回调中报错时,就会返回 rejected
状态的 Promise
对象。
综上所诉,我们得来下方?精辟的一句话:
catch
正常返回 fulfilled
,里面有报错则返回 rejected
总结
经过之前一系列的小案例,我们可以得出以下结论:
pending
状态不会触发then
、catch
、finally
fulfilled
状态会触发后续的then
和finally
回调函数rejected
状态会触发后续的catch
回调函数then
正常返回fulfilled
,里面有报错则返回rejected
catch
正常返回fulfilled
,里面有报错则返回rejected
现在我们再根据这几条总结去看看前面的三道题,相信你现在已经知道了运行结果
当然,Promise
还有很多需要我们去学习的地方,这只能让我们知道 Promise
的运行规则,希望你看了本篇文章,能够从中获得收益
如有不正确的地方欢迎指出,如果你喜欢我的文章,就请动动手指头,扫码关注一下下,我们一起学习一起进步!走向人生巅峰~
![4b2408cad7200f581ccf077447694b05.gif](https://i-blog.csdnimg.cn/blog_migrate/ffa3ae76c6585b25e6ca5d2c90bda6db.gif)