Promise和then
定义
Promise是一个对象,用来返回一个异步函数的处理结果,可以让我们以同步编程的方式来进行异步操作,从而避免层层嵌套的回调地狱出现。
Promise的返回机制
那么Promise是如何实现的呐?Promise对象对三种状态,等待状态、成功状态以及失败状态。这三种状态是由Promise对象内的回调函数来决定的:
- 当回调没有进行返回的时候,Promise处理等待状态(成功还是失败都不确定,因为没有返回)。
- 当回调执行成功,Promise处于成功状态,并通过resolve()方法将执行的结果传递出去(我们可以在.then的回调函数中获取这个返回的结果)
- 当回调执行失败,Promise处于失败状态,通过reject将错误传递出去
then的返回机制
那么Promise+then是如何避免回调地狱的呐?这就要来说说then的原理。当Promise成功执行之后,异步操作(Promise的回调)的结果通过resolve()被传入到then的回调函数中。在then的回调中:
- 如果没有返回值,就默认是返回一个Promise对象;
- 如果有返回值,但不是Promise对象,则默认通过Promise.resolve()的方法将其返回;
- 如果返回的就是一个Promise对象,则将这个Promise对象返回。
解决回调地狱
正是由于then的返回机制,使得then()方法可以链式编程使用,并且后面的then以前面输出的结果为输入,从而使得我们可以用同步编程的方式来进行异步操作,从而用避免层层嵌套的回调地狱的出现。
Promise的静态方法
除此之外,Promise还有一些静态方法,例如:Promise.all()、Promise.allSettled()以及Promise.race()等。
Promise.all()
Promise.all()可以以数组的形式传入多个Promise对象,并将多个异步操作的结果进行返回,但是只要有一个异步操作调用了reject,该方法就是停止并且进入catch。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 0)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 0)
})
Promise.all([p1, p2, p3]).then(res => {
console.log(res)
})
Promise.allSettled()
Promise.allSettled()与Promise.all()类似,区别是,then 始终可以获取到异步的状态,哪怕其中有一个失败。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 0)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 0)
})
Promise.allSettled([p1, p2, p3]).then(res => {
console.log(res)
})
Promise.race()
Promise.race()使用和 all 一样,但是只返回第一个结果,不管成功或失败。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(1)
}, 500)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 200)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 300)
})
Promise.race([p1, p2, p3])
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err) // 2
})