1. 为什么要对Axios进行二次封装?
如果不对Axios进行二次封装,可以想象到每次调用Axios都需要对其重复的进行配置。
并且封装Axios,也能够使得每次请求的入口相同,更加便于管理。
2. 如何对Axios进行二次封装
首先我们需要构建出一个axios实例用于发送请求,以及需要绑定一些方法,使得每次请求的入口都是这些方法。其次,错误处理和令牌数据携带需要在Axios拦截器进行构造。
构建HTTP请求类:
import axios from "axios";
import baseConfig from "./baseConfig";
import { InterceptorController } from "./InterceptorController";
class HTTP {
constructor(extraConfig) {
const mergeConfig = {...baseConfig,...extraConfig};
this.ins = axios.create({
...mergeConfig
})
/** 创建拦截器实例 */
const interceptorController = new InterceptorController(this.ins)
interceptorController.addRequestInterceptor.apply(this);
interceptorController.addResponseInterceptor.apply(this);
}
/** 通用的请求方法 */
async request(url, config) {
try {
return await this.ins({ url, ...config, });
} catch (error) {
throw error.response ? error.response.data : error;
}
}
post(url, data, config){
return this.request(url, { ...config, data, method: 'POST' });
}
get(url, config) {
return this.request(url, { ...config, method: 'GET' });
}
}
构建Axios拦截器:
import qs from 'qs';
import { responseCodeMap } from 'responseCodeMap.js';
/** axios拦截控制器 */
export class InterceptorController {
/**
* @param ins - axios实例
*/
constructor(ins) {
this.ins = ins;
/** 用于超时重试计数 */
this.retryCount = 1;
};
addRequestInterceptor() {
this.ins.interceptors.request.use((config) => {
loading();
/** 携带token,假设token存入了store中 */
const token = store.commit('token');
if(store.commit('getToken')){
config.headers.token = token;
}else{
redirectTo('login');
}
config.data = qs.stringify(config.data);
},(error) => {
closeLoading();
/** 重定向到错误页面 */
redirectTo('error' + error.response.status);
return Promise.reject(error);
});
}
addResponseInterceptor(){
this.ins.interceptors.response.use((res) => {
closeLoading();
return res;
},(error) => {
closeLoading();
/** 超时重发请求 */
if(error.code === 'ECONNABORTED' && error.message.includes('timeout')){
const config = error.config;
if(this.retryCount <= 3){
this.retryCount++;
console.warn(`请求超时,第${this.retryCount - 1}次重试`);
return new Promise(resolve => {
setTimeout(() => {
resolve(this.ins(config));
}, 1000);
});
}else{
console.error('请求重试失败,已达最大重试次数');
this.retryCount = 1;
$message.error('网络请求超时,请稍后重试');
}
}
})
}
}