1、取消重复请求
场景:一般点击了A按钮,请求已经发送,请求还没完的时候,再次点击按钮,又会发送新的请求。此场景,解决办法也有很多,例如loading效果,或者使用react-query库。在此我们使用Promise的特性解决
方案:创建一个类,使用Promise.race()的特性,每次请求时,在当前请求身旁埋一个雷,也就是说每次发送请求时,创建一个Promise数组,数组里面包含当前请求的Promise和自己新建的Promise,如果说在此发送请求,发现promise正在请求中,就把这个请求炸掉,开启新的请求
cancelAblePromise.ts
export default class CancelAblePromise {
pendingPromise : Promise<any> | null,
reject : Function;
constructor() {
this.pendingPromise = null;
this.reject = () => {};
}
request(requestFn : Function){
if(this.pendingPromise){
this.cancel('取消请求');
}
const cancelPromise = new Promise((resolve,reject) => this.reject = reject);
this.pendingPromise = Promise.race([requestFn,cancelPromise]);
return this.pendingPromise;
}
cacel(reason : string){
this.reject(reason);
this.pendingPromise = null;
}
}
test.ts
useEffect(() => {
request();
}, []);
const requestDemo = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('赢了');
}, 2000);
});
};
const request = async () => {
const cancelPromise = new cancelAblePromise();
for (let i = 0; i < 5; i++) {
cancelPromise
.request(requestDemo)
.then((res) => console.log(res))
.catch((error) => console.log(error));
}
};
2.超时控制
场景:转盘问题,一个抽奖转盘动画效果有5秒,但是一般来说向后端请求转盘结果只需要不到一秒,因此请求结果至少得等5秒才能展现给用户。
1.转盘动画还未完成,请求结果已经拿到了,此时要等到动画完成再展示结果给用户。
2.转盘动画完成了,请求结果还未拿到,此时需要等待结果返回(可以设置请求超时时间)。
思路:设置个超时的Promise,使用Promise.race,看Request和超时Promise,谁先返回结果。
function sleep(delay){
return new Promise((resolve,reject) => {
setTimeout(() => {reject('超时')},delay)
})
}
function timeoutPromise(requestFn,timeout){
return Promise.race([requestFn,sleep(timeout)]);
}
-----自定义实现Promise.race------
function timeoutPromise(requestFn,timeout){
const promises = [requestFn(),sleep(timeout)];
return new Promise((resolve,reject) => {
for(const promise of promises){
promise.then(res => resolve(res)).catch(error => reject(error));
}
})
}
3.Promise实现串行
思路:
1.串行就需要Promise依据上一次的结果一直then下去
2.这一次需要依赖上一次的值考虑使用reduce
function execute(tasks) {
return tasks.reduce(
(previousPromise, currentPromise) => previousPromise.then((resultList) => {
return new Promise(resolve => {
currentPromise().then(result => {
resolve(resultList.concat(result))
}).catch(() => {
resolve(resultList.concat(null))
})
})
}),
Promise.resolve([])
)
}
网友评论