axios二次封装
因为项目中很多时候需要发起请求的时候有loading效果,避免看起来操作卡顿,或者点击的时候没有任何反馈给用户,所以就想着在发起请求的时候做个全局的loading,这个放在请求拦截封装里是最合适的,业务不需要关心怎么实现,只要配置即可
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from "axios";
import { message as Message, Spin } from "antd";
import ReactDOM from "react-dom";
interface IAxiosResponse extends AxiosResponse {
config: InternalAxiosRequestConfig & { loading?: boolean }
}
const createLoadingDOM = () => {
const dom = document.createElement('div')
dom.setAttribute('id', 'loading')
document.body.appendChild(dom)
ReactDOM.render(<Spin />, dom)
}
const removeLoadingDOM = () => {
const dom = document.getElementById('loading') as HTMLDivElement;
document.body.removeChild(dom!);
}
let requestNum = 0;
const addLoading = () => {
// 增加loading 如果pending请求数量等于1,弹出loading, 防止重复弹出
requestNum++;
if (requestNum == 1) {
createLoadingDOM();
}
};
const cancelLoading = () => {
// 取消loading 如果pending请求数量等于0,关闭loading
requestNum--;
if (requestNum === 0) {
removeLoadingDOM();
};
};
export const createAxiosByInterceptors = (
config?: AxiosRequestConfig
): AxiosInstance => {
const instance = axios.create({
timeout: 60000, //超时配置
withCredentials: true, //跨域携带cookie
...config, // 自定义配置覆盖基本配置
});
// 添加请求拦截器
instance.interceptors.request.use(
function (config: any) {
// 在发送请求之前做些什么
const { loading = true } = config;
let regex = /.+?ccsrf=(.+?)\;.*/
config.headers['Hcsrf'] = document.cookie.match(regex)![1];
if (loading) addLoading();
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
instance.interceptors.response.use(
function (response: IAxiosResponse) {
// 对响应数据做点什么
console.log("response:", response);
const { loading = true } = response.config;
if (loading) cancelLoading();
const { code, data, message } = response.data;
// config设置responseType为blob 处理文件下载
if (response.data instanceof Blob) {
// TODO: 文件下载
// return downloadFile(response);
} else {
if (code === '000000') return data;
else if (code === 'AUTH_EXPIRE') {
// jumpLogin();
// TODO: 跳转登录
} else {
Message.error(message);
return Promise.reject(response.data);
}
}
},
function (error) {
const { loading = true } = error?.config || {};
if (loading) cancelLoading();
if (error.response) {
if (error.response.status === 401) {
// TODO: 跳转登录
// jumpLogin();
}
}
Message.error(error?.response?.data?.message || "服务端异常");
return Promise.reject(error);
}
);
return instance;
};
const request = createAxiosByInterceptors();
export default request;