思路:
-
创建axios拦截器class类(HttpRequest);
-
每次发起请求时,new一个HttpRequest(),记录axios请求序列(可在此添加加载loading),并通过vuex记录axios cancelToken;
-
页面路由切换时,终止已发出的请求,并清空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();