持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情
前言
Promise 是ES6新增的一个异步编程的一个对象,因为JS本身是单线程的,所以当碰到需要做异步操作的时候,我们就得考虑其他方案了,Promise就可以为我们解决这样的问题。
Promise状态
总共有三种状态
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝;
当执行executor中的代码时,处于该状态;
- 已成功(fulfilled): 意味着操作成功完成;
执行了resolve时,处于该状态,Promise已经被兑现;
- 已拒绝(rejected): 意味着操作失败;
执行了reject时,处于该状态,Promise已经被拒绝;
Promise基础使用
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成Promise');
resolve('要返回的数据可以任何数据例如接口返回数据');
}, 2000);
});
p.then(res=>{
console.log('收到返回结果',res)
})
如上,若通过new关键字声明一个Promise对象,则需要传入一个函数,其参数分别为2个回调函数 resolve和reject。
如果resolve回调的不是一个Promise对象,那么这个promise对象就已经确定了状态,表示执行成功了,不可改变,最后可以通过then函数接收这个回调的值。
resolve方法
resolve是一个Promise类的方法,可以直接通过Promise.reslove('gogo')直接调用,等同于
new Promise((resolve)=>resolve(''gogo))
-
情况一:如果resolve传入一个普通的值或者对象,那么这个值会作为then回调的参数。
-
情况二:如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态。
new Promise(function(resolve, reject){
resolve(new Promise(function(resolve, reject){
setTimeout(function(){
resolve('第二个promise回调');
}, 2000);
}))
}).then(res=>{
console.log('res: ', res);
})
- 情况三:如果resolve中传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并且根据then方法的结果来决定Promise的状态。
new Promise(function(resolve, reject){
resolve({
then:function(resolve, reject){
console.log('then方法回调' );
}
})
}).then(res=>{
console.log('res: ', res);
})
then方法讲解
then方法是Promise对象原型上的一个方法,它接收2个参数,一个是成功状态的回调函数,一个是失败状态的回调函数,所以完整写法如下
let p = new Promise(function(resolve, reject){
//做一些异步操作
// setTimeout(function(){
// console.log('执行完成Promise');
// resolve('要返回的数据可以任何数据例如接口返回数据');
// }, 2000);
reject('发生了错误')
});
p.then(res=>{
console.log('收到返回结果',res)
},err=>{
console.log('收到reject请求',err)
})
这里我们reject一个错误回调,可以看到打印结果如下
then方法可以被多次调用,依次都会执行。
then方法也可以有返回值,并且当then方法中的回调函数返回一个结果时,那么它处于fulfilled状态,并且会将结果作为resolve的参数;
-
返回一个普通的值;
-
返回一个Promise;
-
返回一个thenable值;
当then方法抛出一个异常时,那么它处于reject状态;
catch方法
这个方法跟then方法类似,都属于Promise实例对象上的方法,同样也可以多次调用。从字面看不难理解它就是一个捕获错误的方法。
注意的是如果写了catch方法,那then方法里面就不用额外传第二个参数了。
p.then(res=>{
console.log('收到返回结果',res)
}).catch(err=>{
console.log('catch:收到reject请求',err)
})
如果需要多次调用catch,那么在上一个catch需要抛出新的错误,throw new Error('新的错误')。
finally方法
这个方法表示无论Promise对象无论变成fulfilled还是rejected状态,最终都会被执行。
p.then(res=>{
console.log('收到返回结果',res)
}).catch(err=>{
console.log('catch:收到reject请求',err)
}).finally(()=>{
console.log('肯定会执行')
})
all方法
这是一个类方法,是将多个Promise包裹在一起形成一个新的Promise。需要注意的是
-
当所有的Promise状态变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值组成一个数组;
-
当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数;
const p1=new Promise(function(resolve,reject){
resolve('我是p1')
})
const p2=new Promise(function(resolve,reject){
resolve('我是p2')
})
const p3=new Promise(function(resolve,reject){
resolve('我是p3')
})
Promise.all([p1,p2,p3]).then(res=>{
console.log(res);
})
allSettled方法
该方法的特点是
-
该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是rejected时,才会有最终的状态;
-
并且这个Promise的结果一定是fulfilled的;
Promise.allSettled([p1,p2,p3]).then(res=>{
console.log(res);
})
race方法
这个方法用的应该比较少,它的意思是多个Promise,谁先有结果,就先用谁的。
Promise.race([p1,p2,p3]).then(res=>{
console.log(res);
}).catch(err=>{
console.log('race:',err);
})
any方法
-
如果有一个 Promise 的状态为成功(fulfilled),p 的状态为成功(resolved)。
-
如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态。
总结
Promise算是比较常用的一个js对象了,掌握Promise也是必不可少,也是面试经常问的,先掌握使用在然后深入原理。