前言
axios 的库本身是一个基于ajax 封装通用的请求库。为满足个性化业务需求,通常需要进行再封装使用。
封装Axios 之前我们设定一个目标,我们理想中的 axios 是什么样的?
- 请求拦截和统一的错误处理
- 自定义接口返回类型
- 封装前的资料学习
对于封装 Aios 无非我们是对请求前,响应体进行拦截,以及对返回的数据类型进行标注。以下是axios的流程图,由 ChatGPT 生成。在封装中也是对这几个流程进行自定义封装。

封装开始
这是在封装中主要用到的类型,其实也是对应着流程图中,几个主要流程。后面可以CTRL + 鼠标左键,点进去查看类型具体是如何定义的。
import axios, {
/** axios实例类型 */
AxiosInstance,
/** 内部axios请求配置类型 */
InternalAxiosRequestConfig,
/** axios请求配置类型 */
AxiosRequestConfig,
/** 错误对象类型 */
AxiosError,
/** 完整原始响应体类型 */
AxiosResponse,
} from "axios";
axios 最基础的封装
service 是类的成员,其实也就是axios 的实体,具体发送请求的对象。
在构造函数中对 axios 进行最基本的配置,设置 baseURL 以及请求超时时间
class HttpRequest {
service: AxiosInstance;
constructor() {
/**
* 创建axios实例
* 设置一些默认配置项
*
* 项目API基础URL
* 请求超时时间
*/
this.service = axios.create({
baseURL: import.meta.env.VITE_APP_API_URL,
timeout: 5 * 1000,
});
}
请求拦截器
请求拦截器中使用 this.service.interceptors.request.use 方法进去请求拦截,use方法分别接受 3 个 可选参数
点击 use 方法 可以查看到它的类型说明,它分别接收 onFulfilled 、onRejected、options 其实叫什么名字无所畏,管它叫张三、李四还是王二麻子,只是称呼为了方便就按照官方的叫法叫吧




第一个参数: onFulfilled
它的类型来源在源文件中都写的清楚明白,仔细看下可以看到它的类型是泛型V,下面泛型 V 就是 InternalAxiosRequestConfig,那么我们也就知道了 use 方法第一个参数的类型了可以直接定义上去。
作用:在常见的业务中,一般是将token 放在请求头上,作为鉴权使用,人类坐任何运动前的都会进行热身运动,才能更持久,对应电脑也是一样总要有准备运动。都可以放上去,总之在请求前你想做的一些事情你都可以放上去。
第二个参数: onRejected
onRejected 也是个方法,执行发生错误后执行,接收错误对象,一般我们请求没发送出去出现报错时,一般这边不会做什么操作
第三个参数: options
options 是个对象,配置 1. 设置拦截器是否同步执行 默认false 2. 设置拦截器是否运行
代码
import axios, {
/** axios实例类型 */
AxiosInstance,
/** 内部axios请求配置类型 */
InternalAxiosRequestConfig,
/** axios请求配置类型 */
AxiosRequestConfig,
/** 错误对象类型 */
AxiosError,
/** 完整原始响应体类型 */
AxiosResponse,
} from "axios";
class HttpRequest {
service: AxiosInstance;
constructor() {
// ...
/** 请求拦截器 */
this.service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
/**
* set your config
*/
if (import.meta.env.VITE_APP_TOKEN_KEY && getToken()) {
// carry token
config.headers[import.meta.env.VITE_APP_TOKEN_KEY] = getToken();
}
return config;
},
/** 执行发生错误后执行,接收错误对象,一般我们请求没发送出去出现报错时,执行的就是这一步
* 请求错误拦截器
*
**/
(error: AxiosError) => {
return Promise.reject(error);
},
{
/** 设置拦截器是否同步执行 默认false */
synchronous: false,
/** 设置拦截器是否运行 */
runWhen: (config: InternalAxiosRequestConfig) => {
return true;
},
}
);
// ..
}
响应拦截器
响应拦截和请求拦截器大体相同,这边主要讲响应拦截器的类型。响应拦截的类型在源代码中也可以看到和请求拦截器中一样,不同的是响应拦截器中的类型,官方提供一个泛型给我们自己定义,这样我们就可以定义后端返回的数据结构。
看到下面的图是不是和请求拦截器很像,只是我们做的事情略有不同 响应拦截器也接受三个可选参数 onFulfilled onRejected options
onFulfilled
接收一个方法,方法的第一个参数类型是 AxiosResponse<T> 这边的 T 也就是我们前端和后端约定的返回数据的格式由我们自定义 我这边使用 ResponseModel
在响应的时候我们只关注服务端给我们的响应即可,所以最后只需要返回 AxiosResponse["data"]
这边只需根据自己的业务需求来写就行。我给出的代码,只做一个参考。




代码
import axios, {
/** axios实例类型 */
AxiosInstance,
/** 内部axios请求配置类型 */
InternalAxiosRequestConfig,
/** axios请求配置类型 */
AxiosRequestConfig,
/** 错误对象类型 */
AxiosError,
/** 完整原始响应体类型 */
AxiosResponse,
} from "axios";
class HttpRequest {
service: AxiosInstance;
constructor() {
// ...
/** 响应拦截器 */
this.service.interceptors.response.use(
(response: AxiosResponse<ResponseModel>): AxiosResponse["data"] => {
/** 获取响应数据 */
const { data } = response;
/** 获取状态码 */
const { code } = data;
/**根据 code 做出错误处理 */
if (code) {
if (code != 200) {
switch (code) {
case 404:
// the method to handle this code
break;
case 403:
// the method to handle this code
break;
default:
break;
}
return Promise.reject(data.message);
} else {
return data;
}
} else {
return Promise.reject("Error! code missing!");
}
},
(error: AxiosError) => {
return Promise.reject(error);
}
);
// ..
}
即将结束-封装请求方法
这一步其实,封装来说意义不大,因为在前面我们已经对axios几个关键流程进行了处理,这一步主要是为了我们后面方便调用。
import axios, {
/** axios实例类型 */
AxiosInstance,
/** 内部axios请求配置类型 */
InternalAxiosRequestConfig,
/** axios请求配置类型 */
AxiosRequestConfig,
/** 错误对象类型 */
AxiosError,
/** 完整原始响应体类型 */
AxiosResponse,
} from "axios";
class HttpRequest {
service: AxiosInstance;
constructor() {
// ...
/**
* 请求方法
* 返回Promise<ResponseModel<T>>
*/
request<T = any>(config: AxiosRequestConfig): Promise<ResponseModel<T>> {
return new Promise((resolve, reject) => {
try {
this.service
.request<ResponseModel<T>>(config)
.then((response: AxiosResponse["data"]) => {
resolve(response as ResponseModel<T>);
})
.catch((err) => {
reject(err);
});
} catch (error) {
reject(error);
}
});
}
/**封装CRUD */
get<T = any>(config: AxiosRequestConfig): Promise<ResponseModel<T>> {
return this.request<T>({ method: "GET", ...config });
}
post<T = any>(config: AxiosRequestConfig): Promise<ResponseModel<T>> {
return this.request<T>({ method: "POST", ...config });
}
put<T = any>(config: AxiosRequestConfig): Promise<ResponseModel<T>> {
return this.request<T>({ method: "PUT", ...config });
}
delete<T = any>(config: AxiosRequestConfig): Promise<ResponseModel<T>> {
return this.request<T>({ method: "DELETE", ...config });
}
// ..
}
使用
这边我们可以自定义接口的返回的类型
httpRequest.get<string>({
url: "/test",
baseURL: "http://localhost:8081",
}).then((r) => {
console.log(r);
});