虽然本身axios本身就是一个完善的api,但是在工作环境中,为了使用起来更顺手,更好维护,所以一般我们会对axios进行二次封装。我的封装思路是把所有请求都放人一个文件夹,作为配置文件夹,这样的话好维护,然后根据配置去对发送的请求进行处理。代码上简单,有效。以下封装如有特殊需要,可以自己去添加或者修改使用。
interfaceConfig.js文件如下
export default {
login: {
url: 'login',
method: 'post',
},
// 不配method 默认为get。{id} 会根据第三个请求参数进行替换
getInfo:{
url:"user/info/{id}"
},
uploadFild:{
url:'download',
method:'get'
}
}
注意点:如果多人开发,建议按照模块建立多个js文件,最终在配置的index.js文件对这些配置合并。然后封装请求的文件引入index就好。可以解决多人协作开发配置接口冲突问题。
requir.js文件如下,包含的功能有:获取完整的请求路径、取消重复请求、根据环境修改baseUrl、自动去除字符窜首位空格、有contentType传参时,强制修改header内的content-type。
需要安装的依赖 base-64 和 js-cookie yarn add js-cookie base-64 或者 npm i js-cookie base-64,当然你有其他处理成base64和处理cookie的方法可以自行修改。
javascript">import axios from "axios";
import interfaceConfig from "./interfaceConfig";
import Cookies from "js-cookie";
import router from "@/router";
import Base64 from "base-64";
import { ElMessage } from "element-plus";
let baseURL = "/api/v1";
const CancelToken = axios.CancelToken;
let requestList = [];
const instance = axios.create({
// timeout: 5000, // 设置超时时间
baseURL,
withCredentials: true,
});
// 请求拦截器 发送一个请求之前
instance.interceptors.request.use(
(config) => {
const Authorization = Base64.decode(Cookies.get("cloud_serve") || "");
config.headers = {
Authorization,
"Cache-Control": "no-cache",
};
// 添加请求到请求列表
config.cancelToken = new CancelToken((c) => {
// c 为取消请求方法,或者添加白名单允许发送请求
if (requestList.includes(config.url)) {
c();
} else {
requestList.push(config.url);
}
});
return config;
},
(error) => {
return Promise.reject(error);
}
);
//添加响应拦截器
instance.interceptors.response.use(
(response) => {
// 去除已请求成功的请求
requestList = requestList.filter((item) => item !== response.config.url);
return response || {};
},
async (error) => {
if (error.code === "ERR_CANCELED") {
console.log("请求已取消");
return;
}
// 如果其他错误允许再次请求
requestList = requestList.filter((item) => item !== error.config.url);
if (
error.code == "ECONNABORTED" &&
error.message.indexOf("timeout") != -1
) {
console.log("请求超时,请稍后重试");
return;
}
if (error.response.status >= 400 && error.response.status < 500) {
ElMessage.error(error.response.data.message);
} else if (error.response.status === 401) {
ElMessage.error(error.response.data.message || "401:权限失效");
Cookies.remove("xxx");
Cookies.remove("xxxxx");
router.push("/login");
} else if (error.response.status >= 500 && error.response.status < 600) {
ElMessage.error(error.response.data.message || "5XX: 服务错误。");
Cookies.remove("xxx");
Cookies.remove("xxxxx");
router.push("/login");
}
return error.response;
}
);
// 递归处理参数两边空格 和拿掉无效字段
const handleParamsSpance = (params) => {
if (Object.keys(params).length) {
for (const key in params) {
const type = Object.prototype.toString.call(params[key]).slice(8, -1);
if (type === "Object") {
handleParamsSpance(params[key]);
} else if (type === "String" && params[key] !== "") {
params[key] = params[key].trim();
} else if (!params[key] && params[key] !== 0 && params[key] !== false) {
delete params[key];
}
}
}
return params;
};
export function getquestUrl(interfaceConfigName, params = {}, id) {
let url = interfaceConfig[interfaceConfigName].url;
const method = interfaceConfig[interfaceConfigName].method || "get";
if ((id && id !== "undefined") || id === 0) {
if (url.indexOf("{id}") !== -1) {
url = url.replace(/{id}/, id);
} else {
url = url + `/${id}`;
}
}
// 清除参数首尾空格
handleParamsSpance(params);
if (method === "get" && Object.keys(params).length) {
let str = "";
for (const key in params) {
str += `&${key}=${params[key]}`;
}
url = url + str.replace(/&/, "?");
}
return url;
}
// 返回完整地址,一般用通过cookies来下载或者上传
export function getUploadUrl(interfaceConfigName, params = {}, id) {
const url = getquestUrl(interfaceConfigName, params, id);
return location.origin + baseURL + "/" + url;
}
// 请求封装 第二个参数可以传 {} request('接口名称',{},id)
export default function request(interfaceConfigName, params = {}, id) {
const method = interfaceConfig[interfaceConfigName].method || "get";
const url = getquestUrl(interfaceConfigName, params, id);
return instance[method](url, params);
}
调用接口使用方式如下
javascript">// 引入 requestAPi
import request from "@/httpRequest/request";
// 调用API
async submit(){
const res = await request('getInfo', data, this.mealId);
if (res.status === 200) {
//...
}
}
下载文档或者图片调用,如果需要上传formDate格式的参数,注意需要在params里面传入对应的contentType:multipart/form-data 如上图。
补充:多人开发接口按模块划分,避免修改同一个文件冲突