一,前言
上一篇,主要实现 Promise 的核心静态 API(类方法):Promise.all
,主要涉及以下几个点:
- 测试原生 Promise.all 的使用;
- Promise.all 的功能与特性分析;
- Promise.all 的源码实现、执行分析、功能测试;
本篇,继续实现 Promise 静态 API(类方法):Promise.race
;
备注:
- Promise.race 与 Promise.all 实现原理相似;有了 all 的基础 race 就非常简单了;
- Promise.race 面试高频考察点,主要用于解决超时中断问题;
二,Promise.race 简介
1,API 介绍
race:译为“比赛”、“赛跑”;MDN 参考资料
Promise.race
功能(与 Promise.all 对比):
Promise.all
:
- 批处理 promise,返回 promise;
- 全部成功才成功,返回全部结果;
- 一个出错就失败,返回第一个失败结果;
Promise.race
:
- 批处理 promise,返回 promise;
- 无论成功还是失败,谁快就返回谁;
2,原生 Promise.race 功能测试
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Promise 执行完成:成功")
resolve('success')
}, 1000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Promise 执行完成:失败")
reject('fail')
}, 3000);
})
Promise.race([p1, p2]).then((data) => {
console.log('then', data);
}).catch((err) => {
console.log('catch', err);
})
// 执行结果:
// 1 秒后打印“Promise 执行完成:成功” + “then success”;
// 3 秒后打印“Promise 执行完成:失败”;
备注:
- 虽然
Promise.race
在 1 秒后就返回了结果,但实际一共执行了 3 秒才完成; - 如果数组传入数字,会直接返回成功;
三,Promise.race 实现
1,原理分析
Promise.race
:入参是一个 promise 集合;返回一个 Promise 实例;
Promise.race
内部return new Promise(...)
- 执行所有 promise,使用最先返回的结果(不管成功还是失败);
p.then(resolve, reject)
就看谁先进入 then;
2,代码实现
static race (promises) {
return new Promise((resolve, reject)=>{
for(let i = 0; i < promises.length; i++){
let p = promises[i];
if(p && typeof p.then === 'function'){
p.then(resolve, reject) // 使用第一个执行成功的结果
}else{
resolve(p)
}
}
})
}
3,功能测试
传入数字、成功/失败 promise,表现与原生 promise 一致
四,Promise.race 应用:解决超时问题
借助 Promise.race
特性,为 promise 绑个炸弹:
// 包装 promise,使之具备新功能:控制 promise 状态
function wrap(p1){
let abort;
let p = new Promise((resolve, reject)=>{
// 拿到 p 的 reject,以便于随时更新 p 的状态
abort = reject;
})
// Promise.race:相当于给 p1 绑了一个定时炸弹 p
let p2 = Promise.race([p, p1]);
p2.abort = abort;// p2 就获得炸弹的遥控器
return p2;
}
超时了,就直接引爆:
let p1 = new Promise((resolve, reject)=>{
abort = reject;
setTimeout(() => {
resolve('成功')
}, 3000);
})
let p2 = wrap(p1);
p2.then((data)=>{
console.log('then', data)
},(err)=>{
console.log('err', err)
})
setTimeout(() => {
p2.abort('已超时')
}, 1000);
// 执行结果:1 秒后输出"err 已超时",3 秒全部执行完成
五,结尾
本篇,主要实现了 Promise 静态 API(类方法):Promise.race
,主要涉及以下几个点:
- 测试原生 Promise.race 的使用;
- Promise.race 的功能与特性分析;
- Promise.race 的源码实现、执行分析、功能测试;
下一篇,继续 Promise 静态 API:Promise.allSettled
和 Promise.any
;
维护记录
- 20211106
- 添加 Promise.race 应用;(仍需完善)