最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 规避容器组件发送重复请求

    正文概述 掘金(菩提谛听)   2021-07-19   564

    问题

    最近在做前端优化时,发现很多容器组件对同一个接口发起了重复调用。这是可优化的,使得在极短时间内发起的重复请求控制只请求一次,然后将结果resolve给所有的请求即可。实现原理也很简单就是将同一个请求放入请求队列中,直到有一个请求结果返回时,将请求队列所有的内容resolve这个结果即可。

    伪代码实现如下

    针对问题代码实现如下所示:

    function requestOnceWrap(fn, ctx = null, wait = 0) {
      const resolveQueue = [];
      const rejectQueue = [];
      let requestTime = '';
    
      function request(...args) {
        return new Promise(async (resolve, reject) => {
          if (resolveQueue.length || (requestTime && Date.now() - requestTime <= wait)) {
            resolveQueue.push(resolve);
            rejectQueue.push(reject);
          } else {
            if (!requestTime) requestTime = Date.now();
            try {
                const res = await fn.apply(ctx, args);
                [resolve, ...resolveQueue].forEach(resolve => resolve(response));
            } catch(e) {
                [reject, ...rejectQueue].forEach(reject => reject(err));
            }
            resolveQueue.length = 0;
            rejectQueue.length = 0;
          }
        });
      };
    
      return request;
    };
    

    缓存

    针对不常变动的数据,也可以将请求结果进行缓存,再次请求数据时可以直接使用缓存的结果。

    function requestOnceWrap(fn, ctx = null, wait = 0) {
      const resolveQueue = [];
      const rejectQueue = [];
      let requestTime = '';
      // 初始化缓存
      let cache = null;
    
      function request(...args) {
        return new Promise(async (resolve, reject) => {
          // 已有缓存数据,直接 return 数据
          if (cache) {
              return resolve(cache);
          }
          if (resolveQueue.length || (requestTime && Date.now() - requestTime <= wait)) {
            resolveQueue.push(resolve);
            rejectQueue.push(reject);
          } else {
            if (!requestTime) requestTime = Date.now();
            try {
                const res = await fn.apply(ctx, args);
                // 进行结果缓存
                cache = res;
                [resolve, ...resolveQueue].forEach(resolve => resolve(response));
            } catch(e) {
                [reject, ...rejectQueue].forEach(reject => reject(err));
            }
            resolveQueue.length = 0;
            rejectQueue.length = 0;
          }
        });
      };
    
      return request;
    };
    

    请求重试

    如上的warp函数对于所有的请求要么就是全部resolve,要么就是全部reject,没有重试机制。但是对于部分网络问题造成的请求错误如:409、403、502等http code是可以进行重试机制的,从而实现请求正常返回的,伪代码实现如下:

    const MAX_RETRY_COUNT = 3;
    const requestRetry = async (fn, config = {
        retry: 0,
        onSuccess: (res) => {},
        onError: (err) => {},
    }) => {
        try {
            const res = await fn();
            config.onSuccess(res);
        } catch(e) {
            if (config.retry < MAX_RETRY_COUNT) {
                await requestRetry(fn, {
                    retry: config.retry + 1,
                    onSuccess: (res) => {},
                    onError: (err) => {},
                })
            } else {
                config.onError(e);
            }
        }
    };
    

    起源地下载网 » 规避容器组件发送重复请求

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元