zoukankan      html  css  js  c++  java
  • vue切换路由时,取消所有axios请求

    需求场景,由于某些请求很耗时,比如大文件上传、下载,当用户在当前页面发起请求后,又不想等待了,想去其他页面看看。如果不取消此类请求,就会在下一个页面莫名其妙地弹出成功或失败结果,也会影响页面响应。

    其实,要不要取消前一个页面的请求是根据实际情况确定的,如果希望在浏览其他页面时文件继续上传,就不能取消。现在,我们只讨论下需要取消上个页面请求的代码实现:

    一、看下axios官网的介绍:

    可以使用 CancelToken.source 工厂方法创建 cancel token,像这样:

    const CancelToken = axios.CancelToken;
    const source = CancelToken.source();
    
    axios.get('/user/12345', {
      cancelToken: source.token
    }).catch(function(thrown) {
      if (axios.isCancel(thrown)) {
        console.log('Request canceled', thrown.message);
      } else {
         // 处理错误
      }
    });
    
    axios.post('/user/12345', {
      name: 'new name'
    }, {
      cancelToken: source.token
    })
    
    // 取消请求(message 参数是可选的)
    source.cancel('Operation canceled by the user.');

    还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:

    const CancelToken = axios.CancelToken;
    let cancel;
    
    axios.get('/user/12345', {
      cancelToken: new CancelToken(function executor(c) {
        // executor 函数接收一个 cancel 函数作为参数
        cancel = c;
      })
    });
    
    // cancel the request
    cancel();

    可以看出,取消请求需要两个步骤,一是请求配置设置cancelToken,二是取消时调用cancel方法。

    官网提供的两种方式,第一种通过CancelToken类的source方法,返回具体的cancelToken和对应的cancel方法;第二种通过CancelToken的构造函数new CancelToken(executor),返回具体的cancelToken,同时在executor回调中获得cancel方法。

    二、查看axios源码:

    对应第一种方式:可以看出source方法内部还是调用了CancelToken的构造函数,最后将token和对应的cancel封装成一个对象返回。

    /**
     * Returns an object that contains a new `CancelToken` and a function that, when called,
     * cancels the `CancelToken`.
     */
    CancelToken.source = function source() {
      var cancel;
      var token = new CancelToken(function executor(c) {
        cancel = c;
      });
      return {
        token: token,
        cancel: cancel
      };
    };

    对应第二种方式:可以看出 构造函数会将cancel方法当做参数传递给executor的回调函数,所以我们才可以在回调中获得cancel方法。

    /**
     * A `CancelToken` is an object that can be used to request cancellation of an operation.
     *
     * @class
     * @param {Function} executor The executor function.
     */
    function CancelToken(executor) {
      if (typeof executor !== 'function') {
        throw new TypeError('executor must be a function.');
      }
    
      var resolvePromise;
      this.promise = new Promise(function promiseExecutor(resolve) {
        resolvePromise = resolve;
      });
    
      var token = this;
      executor(function cancel(message) {       // 关键代码
        if (token.reason) {
          // Cancellation has already been requested
          return;
        }
    
        token.reason = new Cancel(message);
        resolvePromise(token.reason);
      });
    }

     三、实现我们的代码

    ① 在请求拦截器处,设置cancelToken,并且将cancel方法绑定在Vue原型的$httpRequestList 数组上,在这里我还用MAX_CANCEL_TOKEN_NUM 对保存的cancel方法数量做了限制。

    const CANCEL_TOKEN = axios.CancelToken;
    const MAX_CANCEL_TOKEN_NUM = 2000;
    Vue.prototype.$httpRequestList = [];
    
    axios.interceptors.request.use(
      config => {
        config.CancelToken = new CANCEL_TOKEN(c => {
          if (Vue.prototype.$httpRequestList.length == MAX_CANCEL_TOKEN_NUM) {
            Vue.prototype.$httpRequestList.pop();
          }
          Vue.prototype.$httpRequestList.unshift(c);
        })
        return config;
      },
      err => {
        return Promise.reject(err);
      });

    ② 路由切换时,遍历 Vue.prototype.$httpRequestList 执行每一个cancel方法。 是不是放在afterEach方法中有待斟酌。。。

    /* 全局后置钩子 */
    router.afterEach(function (to, from) {
      Vue.prototype.$httpRequestList.forEach(cancel => {
        cancel()
      });
    });

    参考:http://www.axios-js.com/zh-cn/docs/#取消

              https://github.com/axios/axios/blob/master/lib/cancel/CancelToken.js

    --------学习 交流 提升-----------
  • 相关阅读:
    杰我教育-新老学员交流会
    来杰我学IT,好就业
    怎么创建maven项目
    项目开发生命周期
    2015年12月28日,我工作了
    SSH架构图及各部分知识点
    jsp基础大全
    网站创建过程(二)
    网站创建过程(一)
    python+Django+mysql环境搭建
  • 原文地址:https://www.cnblogs.com/blogNYGJ/p/14542285.html
Copyright © 2011-2022 走看看