1.为什么要封装axios?封装axios
如果每发起⼀次
HTTP
请求,就要把这些⽐如设置超时时间、设置请求头、根据
项⽬环境判断使⽤哪个请求地址、错误处理等等操作,都需要写⼀遍
这种重复劳动不仅浪费时间,⽽且让代码变得冗余不堪,难以维护。为了提⾼我们的代码质量,我们应该在项⽬中⼆次封装⼀下 axios
再使⽤
axios是单立模式因为每一次请求都需要用到这个axios
首先安装axios-S到生产环境里,
为什么要安装到生产环境里,
因为安装到生产环境里开发环境也可以使用 但是生产环境里面开发环境不可以使用,最后在min.js中导入
举个简单个栗子:
axios("http://localhost:3000/data", {
// 配置代码
method: "GET",
timeout: 1000,
withCredentials: true,
headers: {
"Content-Type": "application/json",
Authorization: "xxx",
},
transformRequest: [
function(data, headers) {
return data;
},
], // 其他请求配置...
}).then(
(data) => {
// todo: 真正业务逻辑代码
console.log(data);
},
(err) => {
// 错误处理代码
if (err.response.status === 401) {
// handle authorization error
}
if (err.response.status === 403) {
// handle server forbidden error
} // 其他错误处理.....
console.log(err);
}
);
如果每个⻚⾯都发送类似的请求,都要写⼀堆的配置与错误处理,就显得过于繁琐了
这时候我们就需要对
axios
进⾏⼆次封装,让使⽤更为便利
⼀、如何封装
- 封装的同时,你需要和 后端协商好⼀些约定,请求头,状态码,请求超时时间.......
- 设置接⼝请求前缀:根据开发、测试、⽣产环境的不同,前缀需要加以区分
- 请求头 : 来实现⼀些具体的业务,必须携带⼀些参数才可以请求(例如:会员业务)
- 状态码: 根据接⼝返回的不同 status , 来执⾏不同的业务,这块需要和后端约定好
- 请求⽅法:根据 get 、 post 等⽅法进⾏⼀个再次封装,使⽤起来更为⽅便
- 请求拦截器: 根据请求的请求头设定,来决定哪些请求可以访问
- 响应拦截器: 这块就是根据 后端`返回来的状态码判定执⾏不同业务
设置接⼝请求前缀
- 利⽤ node 环境变量来作判断,⽤来区分开发、测试、⽣产环境
if (process.env.NODE_ENV === 'development') {
axios.defaults.baseURL = 'http://dev.xxx.com'
} else if (process.env.NODE_ENV === 'production') {
axios.defaults.baseURL = 'http://prod.xxx.com'
}
- 在本地调试的时候,还需要在 vue.config.js ⽂件中配置 devServer 实现代理转发,从⽽实现跨域
设置请求头与超时时间
⼤部分情况下,请求头都是固定的,只有少部分情况下,会需要⼀些特殊的请求头,这⾥将普适性的请 求头作为基础配置。当需要特殊请求头时,将特殊请求头作为参数传⼊,覆盖基础配置
在本地调试的时候,还需要在
vue.config.js
⽂件中配置
devServer
实现代理转发,从⽽实现跨域
devServer: {
proxy: {
'/proxyApi': {
target: 'http://dev.xxx.com',
changeOrigin: true,
pathRewrite: { '/proxyApi': ''
}
}
}
}
设置请求头与超时时间
⼤部分情况下,请求头都是固定的,只有少部分情况下,会需要⼀些特殊的请求头,这⾥将普适性的请 求头作为基础配置,当需要特殊请求头时,将特殊请求头作为参数传⼊,覆盖基础配置
const service = axios.create({
...
timeout: 30000, // 请求 30s 超时
headers: {
get: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
// 在开发中,⼀般还需要单点登录或者其他功能的通⽤请求头,可以⼀并配置进来
},
post: {
'Content-Type': 'application/json;charset=utf-8'
// 在开发中,⼀般还需要单点登录或者其他功能的通⽤请求头,可以⼀并配置进来
}
},
})
封装请求⽅法
先引⼊封装好的⽅法,在要调⽤的接⼝重新封装成⼀个⽅法暴露出去
// get 请求
export function httpGet({ url, params = {} }) {
return new Promise((resolve, reject) => {
axios
.get(url, {
params,
})
.then((res) => {
resolve(res.data);
})
.catch((err) => {
reject(err);
});
});
}
// post
// post请求
export function httpPost({ url, data = {}, params = {} }) {
return new Promise((resolve, reject) => {
axios({
url,
method: "post",
transformRequest: [
function(data) {
let ret = "";
for (let it in data) {
ret +=
encodeURIComponent(it) + "=" + encodeURIComponent(data[it]) + "&";
}
return ret;
},
],
// 发送的数据
data,
// •url参数
params,
}).then((res) => {
resolve(res.data);
});
});
}
把封装的⽅法放在⼀个 api.js ⽂件中
import { httpGet, httpPost } from "./http";
export const getorglist = (params = {}) =>
httpGet({ url: "apps/api/org/list", params });
⻚⾯中就能直接调⽤
import { getorglist } from "@/assets/js/api";
getorglist({ id: 200 }).then((res) => {
console.log(res);
});
这样可以把 api 统⼀管理起来,以后维护修改只需要在 api.js ⽂件操作即可
请求拦截器
请求拦截器可以在每个请求⾥加上
token
,做了统⼀处理后维护起来也⽅便
// 请求拦截器
axios.interceptors.request.use(
(config) => {
// 每次发送请求之前判断是否存在token
// 如果存在,则统⼀在http请求的header都加上token,这样后台根据token判断你的登录情况,此处token⼀般是⽤户完成登录后储存到localstorage⾥的
token && (config.headers.Authorization = token);
return config;
},
(error) => {
return Promise.error(error);
}
);
响应拦截器
响应拦截器可以在接收到响应后先做⼀层操作,如根据状态码判断登录状态、授权
// 响应拦截器
axios.interceptors.response.use(
(response) => {
// 如果返回的状态码为200,说明接⼝请求成功,可以正常拿到数据
// 否则的话抛出错误
if (response.status === 200) {
if (response.data.code === 511) {
// 未授权调取授权接⼝
} else if (response.data.code === 510) {
// 未登录跳转登录⻚
} else {
return Promise.resolve(response);
}
} else {
return Promise.reject(response);
}
},
(error) => {
// 我们可以在这⾥对异常状态作统⼀处理
if (error.response.status) {
// 处理请求失败的情况
// 对不同返回码对相应处理
return Promise.reject(error.response);
}
}
);
小结:
封装是编程中很有意义的⼿段,简单的 axios 封装,就可以让我们可以领略到它的魅⼒
封装 axios 没有⼀个绝对的标准,只要你的封装可以满⾜你的项⽬需求,并且⽤起来⽅便,那就
是⼀个好的封装⽅案