Promise基本概念
a.一个promise实例有两个关键属性 如下图所示 PromiseState 称之为 promise实例的 状态
PromiseResult 称之为promise实例的 结果
b.下图可知一个promise实例有三种状态
成功(fulfilled) 失败(reject) 未改变(pedding)
c. 成功态 结果可在then回调中获取 失败态结果可有catch捕获或then的第二个回调中捕获
d. then catch 回调的执行是微任务 (queueMicrotask也是微任务)
一.Promise.all
1.使用
let p1 = new Promise( (res,rej) =>{
res(111)
})
let p2 = new Promise( (res,rej) =>{
setTimeout(()=>{
res(222)
},2000)
})
let p3 = new Promise( (res,rej) =>{
res(333)
})
Promise.all([p1,p2,p3]).then( data =>{
console.log('data',data) // [111,222,333] 可以拿到数组所有成功的结果
}).catch(err =>{
console.log("err",err) // 只要有一个失败 就会拿到失败的结果
})
2.特点
a.all方法返回一个promise实例对象(后面简称promise)
b. all方法返回的promise的状态 : 只要有一个是失败,状态就是失败,只有全部成功,才是成功
c. all方法返回的promise的结果 : 成功状态的结果 是一个数组 数组的每一项与传入的数组中的每一个promise的结果**一 一对应** , 失败状态时的结果是 数组中第一个状态为失败后的结果
d.数组中只要有一个是失败的promise 那么最终的结果就是失败 与数组中元素的顺序无关 与数组中状态改变的先后的顺序无关
3.实现
Promise.all = function (arr){
// 暂不考虑数组中非promise实例的情况
let successValue = []
let times = 0
return new Promise( (res,rej) =>{
arr.forEach( (pro,index) =>{
pro.then( data =>{
times ++
// 数组中promise的索引位置 要与all方法返回的promise的结果的数组中的索引位置一一对应
successValue[index] = data
// 确保可以拿到数组中所有的promise的结果
// 这里不能用successValue长度与arr的长度进行判断 因为[111,empty,333].length === 3 的情况
// 这意味着数组中还有一个promise的状态没有发生改变
if(times === arr.length){
// 说明所有的promise状态都成功改变
res(successValue)
}
}).catch( err =>{
rej(err)
})
})
})
}
Promise.race
1.使用
let p1 = new Promise( (res,rej) =>{
res(111)
})
let p2 = new Promise( (res,rej) =>{
res(222)
})
let p3 = new Promise( (res,rej) =>{
res(333)
})
Promise.race([p1,p2,p3]).then( (data) =>{
console.log("data",data) // data 111
}).catch(err =>{
console.log("err",err)
})
2.特点
a. Promise类上的静态方法
b. 获取数组中状态最先改变的结果
3.实现
Promise.race = function(proList){
return new Promise( (res,rej)=>{
proList.forEach( pro =>{
pro.then( data =>{
res(data)
},(err)=>{
// 这里使用.catch 会有问题
rej(err)
})
})
})
}
Promise.finnaly
1.使用
let p1 = new Promise( (res,rej) =>{
rej(111)
})
p1
.finally((finallyData) =>{
console.log("成功失败都会执行",finallyData) // 成功失败都会执行 undefined
})
.then((data) =>{
console.log("成功的回调",data) // 成功的回调 111
})
.catch(err =>{
console.log("失败的回调",err)
})
2.特点
a. finally回调是微任务,是Promise原型上的方法
b. 不管成功还是失败都会执行回调
3.实现
Promise.prototype.finally = function(cb){
return this.then((data)=>{
cb()
return data
},(err)=>{
cb()
throw err
})
}