Axios 简单网络请求封装
背景
最近一直在学习前端 Vue3 开发, 已经初步掌握了一些基本的用法。今天偶然发现了前端同事仓库代码里面封装的 axios 请求,和我所常见的版本不一样。仔细阅读了下,大致原理都是差不多的,但是看来更优雅了些。记录下两个版本,也方便后期查看学习或者在新项目中复制使用。
普通版本
我所常见的普遍版本也是我一直在使用的版本。
封装
ts
// src/utils/request.ts
import axios from "axios";
import { ElMessage } from "element-plus";
let request = axios.create({
baseURL: "/api",
timeout: 5000,
});
request.interceptors.request.use((config) => {
return config;
});
request.interceptors.response.use(
(response) => {
return response.data;
},
(error) => {
let message = "";
let status = error.response.status;
switch (status) {
case 404:
message = "请求地址不存在";
break;
case 500:
message = "服务器繁忙";
break;
case 401:
message = "Token 过期";
break;
case 403:
message = "没有权限访问";
break;
}
ElMessage({
type: "error",
message,
});
return Promise.reject(error);
}
);
export default request;
调用方式
ts
// src/api/user/index.ts
import request from "@/utils/request";
import type {
LoginForm,
LoginResponseData,
UserInfoResponseData,
} from "./types";
const API = {
Login: "/user/login",
UserInfo: "/user/info",
};
// 登录接口
export const reqLogin = (data: LoginForm) =>
request.post<any, LoginResponseData>(API.Login, data);
// 获取用户信息
export const reqUserInfo = () =>
request.get<any, UserInfoResponseData>(API.UserInfo);
优雅的版本
封装
ts
// src/types/request.type.ts
export type TResult<T> = {
code: number;
msg: string;
data?: T;
count: number;
};
export enum EResponseCode {
SUCCESS = 200,
}
ts
// src/api/index.ts
import axios, {
AxiosError,
type AxiosInstance,
type AxiosRequestConfig,
type AxiosResponse,
} from "axios";
import { ElNotification } from "element-plus";
import { type TResult, EResponseCode } from "@/types/request.type";
const URL: string = "/";
const config = {
// 默认地址
baseURL: URL,
// 设置超时时间
timeout: 30000,
// 跨域时候允许携带凭证
withCredentials: true,
};
class RequestHttp {
service: AxiosInstance;
public constructor(config: AxiosRequestConfig) {
// 实例化axios
this.service = axios.create(config);
/**
* 请求拦截器
* 客户端发送请求 -> [请求拦截器] -> 服务器
* token校验(JWT) : 接受服务器返回的token,存储到vuex/pinia/本地储存当中
*/
this.service.interceptors.request.use(
(config) => {
return {
...config,
};
},
(error: AxiosError) => {
// 请求报错
Promise.reject(error);
}
);
/**
* 响应拦截器
* 服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
*/
this.service.interceptors.response.use(
(response: AxiosResponse) => {
const { data } = response; // 解构
if (data.code == EResponseCode.SUCCESS) {
return Promise.resolve(data);
} else {
ElNotification.warning(data.msg);
return Promise.reject(data);
}
},
(error: AxiosError) => {
ElNotification.error(error.message);
}
);
}
// 常用方法封装
get<T>(url: string, params?: object): Promise<TResult<T>> {
return this.service.get(url, { params });
}
post<T>(url: string, params?: object): Promise<TResult<T>> {
return this.service.post(url, params);
}
put<T>(url: string, params?: object): Promise<TResult<T>> {
return this.service.put(url, params);
}
delete<T>(url: string, params?: object): Promise<TResult<T>> {
return this.service.delete(url, { params });
}
}
// 导出一个实例对象
export default new RequestHttp(config);
调用方式
ts
// src/api/modules/system.api.ts
import RequestHttp from "../index";
import type { Router } from "@/types/global.type";
export namespace SystemApi {
export const getMenu = () => {
return RequestHttp.get<Router.TApiMenuItem[]>("/system/getMenu");
};
}