zoukankan      html  css  js  c++  java
  • axios切断请求CancelToken;外部控制promise返回

    有时候我们需要对一些请求做出拦截,不让继续请求。

    情景:当同样的接口连续请求时,我们可以把前面的请求在还未响应时,切断。

    今天发现有人将请求接口写在了循环里,并且实现了一个功能,很是窝火。因为我认为把接口放在循环里是不对的,说不出哪不对,它就是不对。

    近期做了axios请求切断。导致了这个功能失效。

    记录一下:如何在拦截器切断统一请求。

    我们封装了request请求拦截器,所以在拦截器里实现切断就可以了。

    // 取消还未完成的同请求
    let pending = [];
    let cancelToken = axios.CancelToken;
    let removePending = config => {
      for (let p in pending) {
        if (pending[p].u === config.url + "&" + config.method) {
          //当前请求在数组中存在时执行函数体
          pending[p].f(); //执行取消操作
          pending.splice(p, 1);
        }
      }
    };

    上面这段代码 先声明了 一个队列;然后定义一个取消请求的方法;

    用队列中每一项的 u属性和 请求的url+method方法做对比,若两者一样,代表是统一个请求。然后执行f方法(切断请求)。再删除队列中的这一项。

    什么时候,想队列中添加数据呢?

    在,请求拦截器中:

        removePending(config);
        config.cancelToken = new cancelToken(c => {
            // 这里的axios标识是用请求地址&请求方式拼接的字符串
            pending.push({ u: config.url + "&" + config.method, f: c });
        });

    在每次请求拦截器中先执行一次拦截的方法,如果条件匹配,则取消请求。如果没有取消本次请求,则执行请求拦截器后面的逻辑。

    紧接着是,给config对象加一个canceltoken对象。new cancelToken的回调函数的第一个参数c,就是切断请求的方法。

    可见,队列中的每一项,记录了本次请求的一个u:uuid,用于识别本次请求的id。这里用url和请求方法拼接成的。有一个弊端是,如果两次请求的参数不一样,同样会识别成同一请求。解决方法是:1、指定一个属性,控制某些请求不切断,或在u属性上加上参数值,参数值不同,就不会识别成 同一请求。

    为了测地拦截重复请求,我们可以在响应拦截器中同样执行一次切断方法:

    removePending(response.config);

    以上做法有什么好处?

    当有很多方法并行请求时,对服务器会产生压力。如果能够取消相同的请求,就会减轻服务器压力。

    axios的cancelToken原理是什么呢?

    其实是用一个外部变量 接受住了promise的resolve方法。从而可以在外部控制promise的执行。resolve传递出一个值,比如是cancel时,执行ajax的abort方法。从而取消请求。

    来一个外部控制promise的例子:

    let outResolve,count = 0;
    let a = function (){
        return new Promise(resolve => {
            outResolve = resolve;
            setTimeout(() => {
                outResolve("111")
            },5000);
        })
    }
    
    a().then(res => {
        console.log(res);//正常5s后会返回结果,但是由于下面的方法,在第2s时,提前结束了promise
    })
    let timer = setInterval(() => {
        count += 1;
        console.log(count);
        if(count == 2){//执行这个代码会在第二秒提前执行promise的resolve方法
            outResolve("外部截断promise")
            clearInterval(timer)
        }
    }, 1000);

  • 相关阅读:
    506Relative Ranks(LeetCode)
    计算二进制中1的个数
    vector<vector<int>> 简单知识介绍
    167. Two Sum II
    561. Array Partition I(LeetCode)
    sizeof 用法部分总结
    530. Minimum Absolute Difference in BST(LeetCode)
    JS计算两个日期之间的天数
    路演会上会登记结论的委员信息页面
    eclipse安装SVN插件
  • 原文地址:https://www.cnblogs.com/fqh123/p/14815441.html
Copyright © 2011-2022 走看看