现在出去面试,不会点promise原理、promise的方法,人家就会觉得你基础知识不扎实,或者是没有亮点,反正就是看不上你,今天我们就来聊一聊promise的各个方法如何实现吧。
Promise.resolve
规范
Promise.resolve返回一个Promise- 传入的参数如果是一个
Promise,则直接返回 - 传入的参数如果不是一个
Promise,则需要new Promise包装一下 小栗子
//非promise对象,非thenable对象
const obj=Promise.resolve('1')
obj.then((response,reject)=>{
console.log(response,reject);
})
console.log(obj);
//promise成功对象
const p=new Promise(resolve=>resolve('2'))
const obj2=Promise.resolve(p).then(res=>console.log(res))
console.log(obj2);
//promise 失败对象
const p2=new Promise((resolve,reject)=>reject('error3'))
const obj3=Promise.resolve(p2).catch(res=>console.log(res))
console.log(obj3)
源码实现
Promise.myResolve=value=>{
//如果是promise对象,则直接返回
if(value&& typeof value ==='object'&& (value instanceof Promise)){
return value
}
//否则用promise再包装一下
return new Promise(resolve=>{
resolve(value)
})
}
Promise.all
规范
Promise.all()方法用于将多个Promise实例,包装成一个Promise实例。常用于async/await中,多个await之间没有依赖关系,减少性能消耗。
const p1=Promise.all([p1,p2,p3])
最终p的状态由p1、p2、p3决定,分为2种情况:
- 当p1、p2、p3的状态都为
fullfilled时,p的状态就为fullfilled,此时p1、p2、p3的返回值组成一个数组,返回给p的回调 - 当p1、p2、p3的状态有一个为
rejected时,那么p的状态就为rejected,此时第一个被reject实例的返回值,会返回给p的回调 - 如果其中某个实例不是
Promise对象,则Promise.all会将它转为Promise对象 小栗子
const p1 = Promise.resolve('1')
const p2=new Promise(resolve=>{
setTimeout(() => {
resolve('2')
}, 1000);
})
const p3=new Promise(resolve=>{
setTimeout(() => {
resolve('3')
}, 3000);
})
const p4 = Promise.reject('err4')
const p5 = Promise.reject('err5')
const p11=Promise.all(['23',p2,p3]).then(res=>{
console.log(res);
}).catch(err=>console.log(err))
const p12=Promise.all([p1,p2,p4]).then(res=>{
console.log(res);
}).catch(err=>console.log(err))
const p13=Promise.all([p1,p5,p4]).then(res=>{
console.log(res);
}).catch(err=>console.log(err))
源码实现
Promise.myAll=(promises)=>{
return new Promise((resolve,reject)=>{
let len=promises.length
let result=[]
if(!len){
resolve([])
}
promises.forEach((promise,index)=>{
//有的数组项不是promise对象,需要转化一下
Promise.resolve(promise).then((res)=>{
//将结果存入数组中
result[index]=res
//当所有promise都执行完且成功时,那么将返回的promise结果设置为result
if(index===len-1){
resolve(result)
}
//监听数组项中的每一项, catch 只有有一个失败,那么我们返回的promise也失败了
}).catch(err=>reject(err))
})
})
}
const p1 = Promise.resolve('1')
const p2=new Promise(resolve=>{
setTimeout(() => {
resolve('2')
}, 1000);
})
const p3=new Promise(resolve=>{
setTimeout(() => {
resolve('3')
}, 3000);
})
const p4 = Promise.reject('err4')
const p5 = Promise.reject('err5')
const p11=Promise.myAll(['23',p2,p3]).then(res=>{
console.log(res);
}).catch(err=>console.log(err))
const p12=Promise.myAll([p1,p2,p4]).then(res=>{
console.log(res);
}).catch(err=>console.log(err))
const p13=Promise.myAll([p1,p5,p4]).then(res=>{
console.log(res);
}).catch(err=>console.log(err))
const p14=Promise.myAll([]).then(res=>{
console.log(res);
})
Promise.race
规范
只要p1、p2、p3实例之中有一个状态率先改变,那么p的状态就跟着改变。 应用场景
- 后端代码部署在多台服务器上,前端race中写各个服务器连接方法,谁响应快就用谁的。
- 前端代码发起请求或异步回调时,在规定时间内未请求成功就直接走失败方法。 小栗子
const p1=Promise.resolve('1')
const p2=new Promise(resolve=>{
setTimeout(() => {
resolve('2')
}, 1000);
})
const p3=new Promise(resolve=>{
setTimeout(() => {
resolve('3')
}, 2000);
})
const p4=Promise.reject('err4')
const p11=Promise.race([p1,p2]).then(res=>{
console.log(res); //1
})
const p14=Promise.race(['33',p1]).then(res=>{
console.log(res); //33
})
const p12=Promise.race([p3,p2]).then(res=>{
console.log(res); //2
})
const p13=Promise.race([p2,p4]).then(res=>{
console.log(res);
}).catch(err=>console.log(err)) // err4
源码实现
Promise.myRace=(promises)=>{
return new Promise((resolve,reject)=>{
promises.forEach(promise=>{
Promise.resolve(promise).then(res=>resolve(res)).catch(err=>reject(err))
})
})
}
const p1=Promise.resolve('1')
const p2=new Promise(resolve=>{
setTimeout(() => {
resolve('2')
}, 1000);
})
const p3=new Promise(resolve=>{
setTimeout(() => {
resolve('3')
}, 2000);
})
const p4=Promise.reject('err4')
const p11=Promise.myRace([p1,p2]).then(res=>{
console.log(res); //1
})
const p14=Promise.myRace(['33',p1]).then(res=>{
console.log(res); //33
})
const p12=Promise.myRace([p3,p2]).then(res=>{
console.log(res); //2
})
const p13=Promise.myRace([p2,p4]).then(res=>{
console.log(res);
}).catch(err=>console.log(err)) // err4
Promise.allSettled
规范
有时候我们想要在一组
promise全部执行完,在继续下面的操作,不管每一个实例的结果是fullfilled还是rejected,都等他全部执行完,再执行后面的代码。Promise.all是只要有一个reject,就会中断执行,不符合我们的需求。
小栗子
const p1 = Promise.resolve(1)
const p2 = new Promise((resolve) => {
setTimeout(() => resolve(2), 1000)
})
const p3 = new Promise((resolve) => {
setTimeout(() => resolve(3), 3000)
})
const p4 = Promise.reject('err4')
const p5 = Promise.reject('err5')
// 1. 所有的Promise都成功了
const p11 = Promise.allSettled([ p1, p2, p3 ])
.then((res) => console.log(JSON.stringify(res, null, 2)))
// 输出
/*
[
{
"status": "fulfilled",
"value": 1
},
{
"status": "fulfilled",
"value": 2
},
{
"status": "fulfilled",
"value": 3
}
]
*/
// 2. 有一个Promise失败了
const p12 = Promise.allSettled([ p1, p2, p4 ])
.then((res) => console.log(JSON.stringify(res, null, 2)))
// 输出
/*
[
{
"status": "fulfilled",
"value": 1
},
{
"status": "fulfilled",
"value": 2
},
{
"status": "rejected",
"reason": "err4"
}
]
*/
// 3. 有两个Promise失败了
const p13 = Promise.allSettled([ p1, p4, p5 ])
.then((res) => console.log(JSON.stringify(res, null, 2)))
// 输出
/*
[
{
"status": "fulfilled",
"value": 1
},
{
"status": "rejected",
"reason": "err4"
},
{
"status": "rejected",
"reason": "err5"
}
]
*/
源码实现
Promise.myAllSettled=(promises)=>{
return new Promise((resolve,reject)=>{
let result=[]
let len=promises.length
if(!len){
resolve([])
}
promises.forEach((promise,index)=>{
Promise.resolve(promise).then(res=>{
result[index]={
statu:'fulfilled',
value:res
}
if(index===len-1){
resolve(result)
}
}).catch(err=>{
result[index]={
statu:'rejected',
value:err
}
if(index===len-1){
resolve(result)
}
})
})
})
}
const p1 = Promise.resolve(1)
const p2 = new Promise((resolve) => {
setTimeout(() => resolve(2), 1000)
})
const p3 = new Promise((resolve) => {
setTimeout(() => resolve(3), 3000)
})
const p4 = Promise.reject('err4')
const p5 = Promise.reject('err5')
// 1. 所有的Promise都成功了
const p11 = Promise.myAllSettled([ p1, p2, p3 ])
.then((res) => console.log(JSON.stringify(res, null, 2)))
const p12 = Promise.myAllSettled([ p1, p2, p4 ])
.then((res) => console.log(JSON.stringify(res, null, 2)))
const p13 = Promise.myAllSettled([ p1, p4, p5 ])
.then((res) => console.log(JSON.stringify(res, null, 2)))
结尾
如有错误,欢迎大家指正啦