Promise解决实际问题

1、取消重复请求

场景:一般点击了A按钮,请求已经发送,请求还没完的时候,再次点击按钮,又会发送新的请求。此场景,解决办法也有很多,例如loading效果,或者使用react-query库。在此我们使用Promise的特性解决

方案:创建一个类,使用Promise.race()的特性,每次请求时,在当前请求身旁埋一个雷,也就是说每次发送请求时,创建一个Promise数组,数组里面包含当前请求的Promise和自己新建的Promise,如果说在此发送请求,发现promise正在请求中,就把这个请求炸掉,开启新的请求

cancelAblePromise.ts
export default class CancelAblePromise {
    pendingPromise : Promise | 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([])
    )
}

你可能感兴趣的:(Promise解决实际问题)