Promise是什么?
Promise是异步编程的一种新的解决方案,比以往通过回调函数和事件来解决异步操作更加强大。
简单来说Promise就是一种异步编程的方式
Promise有什么用?
解决回调地狱
setTimeout(function () { //第一层
console.log('武林要以和为贵');
setTimeout(function () { //第二程
console.log('要讲武德');
setTimeout(function () { //第三层
console.log('不要搞窝里斗');
}, 1000)
}, 2000)
}, 3000)
输出结果:
武林要以和为贵
要讲武德
不要搞窝里斗
上面的函数第一层是3s,第二层为2s,第三场是1s,但是由于是使用回调函数嵌套回调函数的方式,实现代码顺序执行而出现的一种操作,这种回调函数一层套一层的代码被称为回调地狱,它会造成我们的代码可读性非常差,后期不好维护。
为了解决回调地狱问题,promise横空出世!
promise中使用链式调用的方式解决了回调函数嵌套的情况,让代码看起来更像是同步代码,并且Promise有三种状态,pending(等待态),fulfilled(成功态),reject(失败态),重点:promise的状态是不可逆的,一旦发生改变就不可回溯
看以下代码:
const p = new Promise((resolve,reject)=>{
resolve(111)
reject(222)
})
p.then((res)=>{
console.log('成功的回调',res);
}).catch((err)=>{
console.log('失败的回调',err);
})
输出结果:
成功的回调 111
我们先将promise的状态置为resolve,后面如果再置为reject则不生效。
再看以下代码:
const p = new Promise((resolve,reject)=>{
resolve(111)
reject(222)
})
p.then((res)=>{
console.log('成功的回调',res);
return res*10
}).then((res1)=>{
console.log('成功的回调2',res1);
})
.catch((err)=>{
console.log('失败的回调',err);
})
猜猜这个代码段的输出结果为什么?
答案为:
成功的回调 111
成功的回调2 1110
从代码中,我们可以看到,在执行第一个then的时候,我们将res的值乘以十以后再return出来,而第一个then返回的值为第二个then中传入的值,这就是promise的链式调用。
Promise中常用的API
promise.all()
概念:在执行多个promise实例时,当所有的promise都执行完毕了才将返回值放入一个数组返回,重点:如果有一个promise的状态为reject(失败)那么其他的promise不再执行,并返回失败的回调。
看代码:
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('p1')
},1000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('p2')
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('p3')
},3000)
})
Promise.all([p1,p2,p3]).then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
})
输出结果:
[ 'p1', 'p2', 'p3' ]
当有一个Promise为失败态时:
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('成功的p1');
resolve('p1')
},1000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('失败的p2');
reject('p2')
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('成功的p3');
resolve('p3')
},3000)
})
Promise.all([p1,p2,p3]).then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
})
输出结果:
成功的p1
失败的p2
p2
成功的p3
从上面的代码可以看出来,只返回了p2一个reject的返回值,而p1、p3的resolve返回值并没有被返回,但是p1、p3中的输出都被输出了,也就是说,虽然他们的resolve并没有被返回,但是他们这两个promise仍会被执行在这两个promise中的操作仍会生效,只是不会有返回值。
Promise.race()
概念:返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝,也就是说race同样是可以传入多个promise组成的数组,但是只返回一个promise,谁跑的快就输出谁
看代码:
var n = 1;
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('失败的p1');
reject('p1')
},1000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('成功的p2');
resolve('p2')
},2000)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
n++;
console.log('成功的p3',n);
resolve('p3')
},3000)
})
Promise.race([p1,p2,p3]).then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
})
输出结果:
失败的p1
p1
成功的p2
成功的p3 2
这里很明显,p1的定时器只有1s所以p1是跑的最快的,所以Promise返回的是reject失败态,并返回p1。
如果定时器时间一样呢?
var n = 1;
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
n++;
console.log('成功的p3',n);
resolve('p3')
},1000)
})
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('失败的p1');
reject('p1')
},1000)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('成功的p2');
resolve('p2')
},1000)
})
Promise.race([p1,p2,p3]).then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
})
输出结果:
成功的p3 2
p3
失败的p1
成功的p2
定义在最前面的p3先输出,返回一个成功的promise