思路:

  1. 创建axios拦截器class类(HttpRequest);

  2. 每次发起请求时,new一个HttpRequest(),记录axios请求序列(可在此添加加载loading),并通过vuex记录axios cancelToken;

  3. 页面路由切换时,终止已发出的请求,并清空axios请求序列提升系统性能;

import axios from "axios";
 
class HttpRequest {
  constructor() {
    this.baseURL = process.env.NODE_ENV === "production" ? "" : "../../";
    this.timeout = 3000;
    // 可根据Object.keys(this.queue).length判断队列中是否还有请求,从而控制loading显示
    this.queue = {}; // 专门用来维护请求队列,页面切换需要取消请求
  }
  setInterceptor(instance, url) {
    instance.interseptors.request.use((config) => {
      // 开起loading 当序列为空的时候开启loading(第一次进来)
      if (!Object.keys(this.queue).length) {
        //开起loading
      }
      // 将请求添加值请求队列
      this.queue[url] = true;
 
      const CancelToken = axios.cancelToken;
      config.cancelToken = new CancelToken((c) => {
        console.log("c: ", c);
        // c 就是当前取消请求都token
        // 可存到vuex中,当页面切换或者组件销毁的时候调用出来终止请求
 
        // store.commit('set_token', c); // 同步将取消方法存入vuex
 
        // 如需清空,可在路由守卫中添加清除逻辑,调L89清空token方法
      });
 
      return config;
    });
 
    instance.interseptors.response.use(
      (res) => {
        //   请求一旦相应,则把该请求从请求序列中移除
        delete this.queue[url];
        //关闭loading 当清空序列的时候关闭loading
        if (!Object.keys(this.queue).length) {
          // 关闭loading
        }
        // 请求成功处理
        if (res.code === 200) {
          console.log("success", res);
          return res.data;
        } else {
          Promise.reject(res);
        }
      },
      (err) => {
        //   请求失败,也需要把该请求从请求序列中移除
        delete this.queue[url];
        //关闭loading 当清空序列的时候关闭loading
        if (!Object.keys(this.queue).length) {
          // 关闭loading
        }
        Promise.reject(err);
      }
    );
  }
  //   所有请求都经过request方法发起
  request(options) {
    //   每次请求可以创建一个新的实例,如果业务不复杂,可直接使用axios实例
    let instance = axios.create();
    let config = {
      baseURL: this.baseURL,
      timeout: this.timeout,
      ...options,
    };
 
    this.setInterceptor(instance, config.url);
    return instance(config); // 产生的是一个 promise
  }
  get(url, data) {
    return this.request({
      url,
      method: "get",
      ...data,
    });
  }
  post(url, data) {
    return this.request({
      url,
      method: "post",
      data,
    });
  }
}
 
export default new HttpRequest();