对于一次网络请求简单的来讲可以分为两步:首先是客户端向服务端发起请求;然后服务端响应请求向客户端返回数据。在请求发送之前和数据返回之后我们可以做一个统一的拦截处理,减少代码冗余以及方便后期的维护,所以对axios请求进行封装是很有必要的。
基础配置
import axios, { AxiosInstance, AxiosPromise, AxiosRequestConfig } from "axios"; import _config from "@/utils/config"; interface AdminInstance<T = any> extends AxiosInstance { (config: AxiosRequestConfig): Promise<T>; }; const service: = axios.create({ baseURL: _config.BASE_URL, //服务端地址 timeout: 30 * 1000, headers: { "Content-Type": "application/json; charset=utf-8", }, });请求拦截处理
service.interceptors.request.use( (config: any) => { const token = localStorage.getItem("token"); if (token) config.headers["Authorization"] = token; //设置token return config; }, (error) => { return Promise.reject(error); } );响应拦截处理
service.interceptors.response.use( async response => { if (response.data.code == 200) { return response.data.results } else { Message.error(response.data.error) //异常处理 return Promise.reject(new Error(response.data.error)) } }, async error => { const error_response = error.response || {} //401为token失效登出,特殊处理 if (error_response.status == 401) { MessageBox.confirm( '你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' } ).then(() => { localStorage.removeItem('token') location.reload() }) } else { Message.error(`${error}`) } return Promise.reject(error); } );抛出实例
export default function Request<T>(options: any): Promise<T> { return service(options); }调用
import Request from "../Request"; export default class Login { public static Login(data: any) { return Request({ url: `/auth/oauth2/login`, method: "post", loading: false, data, }); } }
根据需要还可在其中处理全局的加载动画【完整源码】
Request.ts
import axios, { AxiosInstance, AxiosPromise, AxiosRequestConfig } from "axios";
import _config from "@/utils/config";
import { Foundation } from '@/utils/Foundation'
import { Message, MessageBox } from 'element-ui'
import loadEvents from "./Loading";
let loadingCount: number = 0
const loadingInstance = new loadEvents();
interface AdminInstance<T = any> extends AxiosInstance {
(config: AxiosRequestConfig): Promise<T>;
};
const service: AdminInstance = axios.create({
baseURL: _config.BASE_URL,
timeout: 30 * 1000,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
});
service.interceptors.request.use(
(config: any) => {
if (config.loading !== false) {
loadingCount++
loadingInstance.open();
}
const token = localStorage.getItem("token");
if (token) config.headers["Authorization"] = token; //设置to
return config;
},
(error) => {
loadingCount = 0
loadingInstance.close()
return Promise.reject(error);
}
);
service.interceptors.response.use(
async response => {
loadingCount > 0 && loadingCount--
if (loadingCount == 0) {
loadingInstance.close();
}
if (response.data.code == 200) {
return response.data.results
} else {
Message.error(response.data.error || Foundation.get(response, 'data.results.message', 'Error'))
return Promise.reject(new Error(response.data.error || Foundation.get(response, 'data.results.message', 'Error')))
}
},
async error => {
const error_response = error.response || {}
if (error_response.status == 401 ) {
MessageBox.confirm(
'你已被登出,可以取消继续留在该页面,或者重新登录',
'确定登出',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
localStorage.removeItem('token')
location.reload()
})
} else {
Message.error(`${error}`)
}
loadingCount = 0
loadingInstance.close()
return Promise.reject(error);
}
);
export default function Request<T>(options: any): Promise<T> {
return service(options);
}
Loading.ts
import { Loading } from "element-ui";
const loadOption = { text: "请稍等", target: ".el-container", background: 'rgba(0, 0, 0, 0.2)' };
let loadingInstance: any = null;
export default class loadEvents {
open() {
loadingInstance = Loading.service(loadOption);
}
close() {
loadingInstance && loadingInstance.close();
}
}
版权声明:本文为qq_41595903原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。