目标
- 设置默认配置
- 基础域名:baseURL
- 超时时间:timeout
- 请求拦截
体现在headers设置
- token
- expireTimes
- Content-Type
- X-Requested-With
- 响应拦截
- 响应成功后错误码上报
- 响应失败后,提示超时 && 请求重发
- 封装get和post请求
- 使用例子
axios.js
import axios from 'axios';
import { message } from 'antd';
import { sendReport, retryRequest } from './axiosRequestTools';
const SUCCESS_CODE = 0;
const NO_AUTH_CODE = 40001;
const ERR_MSG = '请求失败,请稍后重试!';
const instance = axios.create({
timeout: 30000,
withCredentials: true,
});
instance.interceptors.request.use((config) => {
const token = document.getElementById('token');
const expire_times = document.getElementById('expire_times');
if (token && token.value) {
config.headers['token'] = token.value;
}
if (expire_times && expire_times.value) {
config.headers['expireTimes'] = expire_times.value;
}
config.headers['Content-Type'] =
'application/x-www-form-urlencoded; charset=UTF-8';
config.headers['X-Requested-With'] = 'XMLHttpRequest';
return config;
});
instance.interceptors.response.use(
(response) => {
const { errno, data, msg } = response.data;
if (errno === SUCCESS_CODE) {
return data;
} else {
//根据code决定是否上报打点
//sendReport(errno, instance);
if (errno === NO_AUTH_CODE) {
const isProd = window.location.origin.indexOf('//soft.cn') > -1;
const url = isProd ? 'https://e.cn/' : 'https://trunk.e.cn/';
window.location.href = url;
}
return Promise.reject(msg);
}
},
(error) => {
if (error.response) {
// 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
if (error.response?.status >= 500) {
return Promise.reject(ERR_MSG);
}
return Promise.reject(error.response?.statusText);
}
//错误重试(可选)
//return retryRequest(error, instance)
// 发送请求时出了点问题
return Promise.reject(error.message);
},
);
/** get方法支持传入泛型表示promise resolve后的类型 */
export const get = <Data>({
url,
data = {},
showError = true,
}: {
url: string;
data?: unknown;
showError?: boolean;
}): Promise<Data> => {
return instance.get<Data>(url, { params: data }).catch((error) => {
if (showError) {
message.error(error);
}
return Promise.reject(error);
}) as Promise<Data>;
};
/** post方法支持传入泛型表示promise resolve后的类型 */
export const post = <Data>({
url,
data = {},
showError = true,
}: {
url: string;
data?: unknown;
showError?: boolean;
}): Promise<Data> => {
return instance.post(url, data).catch((error) => {
if (showError) {
message.error(error);
}
return Promise.reject(error);
}) as Promise<Data>;
};
axiosRequestTools.js
export const sendReport = (code, axiosInstance) => {
const data = {
msg: `发生${code}请求错误`,
url,
file: window.loacation.href,
params
}
axiosInstance.post('/ajax/sendodin', qs.stringify({ errData: JSON.stringify(data) }))
}
// 实现 请求错误时重新发送接口
export const retryRequest = (err, axiosInstance) => {
let config = err.config
// config.retry 具体接口配置的重发次数
if (!config || !config.retry) return Promise.reject(err)
// 设置用于记录重试计数的变量 默认为0
config.__retryCount = config.__retryCount || 0
// 判断是否超过了重试次数
if (config.__retryCount >= config.retry) {
return Promise.reject(err)
}
// 重试次数
config.__retryCount += 1
//打印当前重试次数
console.log(config.url + ' 自动重试第' + config.__retryCount + '次')
// 延时处理
const backoff = new Promise(function (resolve) {
setTimeout(function () {
resolve()
}, config.retryDelay || 400)
})
// 重新发起axios请求
return backoff.then(function () {
return axiosInstance(config)
})
}
使用示例 service.js
import { get,post } from '@/utils/axios';
export const getStatusData = () => {
return get({
url: '/api/getStatus',
});
};
export const postData = (data) => {
return post({
url: '/goapi/soft/add',
data,
showError: false,
});
};