首先来看看这四种方法是什么
Promise.all()
(MDN的定义)
- 描述:Promise.all() 方法接收一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,并且只返回一个
Promise
实例, 那个输入的所有promise的resolve回调的结果是一个数组。这个Promise
的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候。它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。 - 使用场景:当我们需要等待多个返回值互不依赖的请求全部完成后再进行下一步操作时,就可以使用Promise.all()。就比如在访问一个页面的时候会调用多个接口查询数据,在c查询的时候,页面上会显示loading,等接口都返回了再隐藏掉loading。
Promise.race()
(MDN的定义)
- 描述:Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
- 使用场景:我们可以利用Promise.race来模拟超时,写一个定时器,到时间就提示用户超时,将请求接口的函数和这个定时器都放到Promise.race中去,如果接口在定时器计时结束之后返回的话,就会抛出超时的提示。
Promise.retry()
- 描述:Promise.retry()在官方没有封装,但是在我们日常开发的时候使用的很多,所以我们一般会自己封装Promise.retry。它实现了失败后重新尝试的功能。这个方法接收一个绑定函数、重试次数、延迟时间
- 使用场景:超时重试
Promise.allSettled()
(MDN的定义)
- 描述:Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
- 使用场景:allSettled不论最后的结果是fulfilled还是rejected,都会将结果存入返回的数组里,适用于多个彼此不依赖的异步任务成功完成时,或者你想知道每个promise的结果时
现在我们自己来实现这四种方法
Promise.all()
Promise.all = function(promises){
return new Promise((resolve,reject)=>{
let result = []
let counter = 0
for(let i = 0;i<promises.length;i++){
// 以防不是promise对象所以用resolve包一下
Promise.resolve(promises[i]).then(res=>{
//为了让返回的结果按顺序排列,这里不能使用result.push
result[i] = res
if(++counter===promises.length){
return resolve(result)
}
},(err)=>{
return reject(err)
})
}
})
}
Promise.race
Promise.race = function(promises){
return new Promise((resolve,reject)=>{
for(item of promises){
Promise.resolve(item).then((res)=>{
resolve(res)
},err=>reject(err))
}
})
}
Promise.retry
/**
* @description: 加入失败后使用失败重试功能,如果5次中有任意一次成功了,就停止尝试并返回
* @param {*}
* @return {*}
* @param {*} fn 绑定函数
* @param {*} times 请求次数
* @param {*} delay 延迟时间
*/
Promise.retry = function(fn,times,delay){
let tryTimes = 0
return new Promise((resolve,reject)=>{
function attempt(){
console.log(tryTimes)
Promise.resolve(fn()).then(res=>{
return resolve(res)
}).catch(err=>{
if(++tryTimes<times){
setTimeout(attempt,delay)
}else{
return reject(err)
}
})
}
attempt()
})
}
Promise.allSettled
- 在Promise.all的基础上实现·
function allSettled(promises){
//只需要把rejected的情况捕获一下,并返回一个正常值,状态就会进入到fulFilled
return Promise.all(promises.map(item=>Promise.resolve(item)
.then(res=>({status:'fulfilled',value:res}),
err=>({status:'rejected',reason:err}))
))
}
- 不基于Promise.all
function allSettled(promises){
return new Promise((resolve)=>{
promises = Array.isArray(promises)?promises:[]
let count = promises.length
let result = []
for(let i = 0;i < promises.length; i++){
Promise.resolve(promises[i]).then(res=>result[i]={status:'fulfilled',value:res},
err=>result[i] = {status:'rejected',reason:err})
.finally(()=>{
if(--count<=0){
resolve(result)
}
})
}
})
}