美文网首页
Promise解决实际问题

Promise解决实际问题

作者: Poppy11 | 来源:发表于2022-09-07 16:58 被阅读0次

    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([])
        )
    }
    

    相关文章

      网友评论

          本文标题:Promise解决实际问题

          本文链接:https://www.haomeiwen.com/subject/gesinrtx.html