http封装
首先说一下我对前端的http请求的封装的理解,应该分为两部分一是ajax封装二是api的封装
ajax封装
在我最早接触前端的时候ajax封装是封装的小黄人(xhr)那套原生的东西,例如:
let xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200 && xhr.status<300 || xhr.status==304){
alert(xhr.responseText);//成功时响应体返回的实体
}else{
alert('Request was unsuccessful:' + xhr.status);//失败时返回响应的状态
}
}
};
xhr.open('get','example.txt',true);
xhr.send(null);
//使用时
xhr.open('get','www.xxx.com',true);//get请求
这种原生的封装的目的是为了能够通过http向服务端请求数据,但是由于项目中会遇到很多情况比如说Content-Type的格式不同和需不需要传递Cookie等,这就需要跟多的封装配置等
于是现在的ajax封装一般都是对axios进行再一次封装了,例如:
import axios from 'axios'
// 设置超时
axios.defaults.timeout = 3 * 60 * 1000;
//http request 拦截器
axios.interceptors.request.use(
(config) => {
//....... 添加处理函数一般是token的cookie设置和Content-Type的格式设置
//.......
return config;
},
(err) => {
return Promise.reject(err);
}
);
//http response 响应拦截器
axios.interceptors.request.use(
(response) => {
return response;
},
(error) => {
//......处理一些错误情况,例如返回404时怎么样等
return Promise.reject(error.response.data);
}
)
//到这里一般就算是对axios的一些配置封装结束了
//但一般我为了适应自己的写法会对axios的请求方式进行一些改变
const ajax = (msg) =>{
return new Promise((resolve, reject)=>{
if (msg.method == 'get') {
msg.params = { ...msg.data }
} else {
msg.data = { ...msg.data }
}
axios(msg).then((res) => {
resolve(res.data)
}).catch((err) => {
reject(err)
});
})
}
export default ajax;
//使用时(已经在main.js中全局引入了)
this.ajax({
url: 'www.xxx.com',
data: {},
method: 'get'
}).then((res)=>{
console.log('res--', res)
})
api封装
对于api的封装是我最想说几句的,因为我经常见到这种封装:
async function getIsOpen (params) {
return await fetchSmart('api/foreign/getIsOpen_v3', {
method: 'post',
params,
})
}
async function testStarted (params) {
return await fetchSmart('api/foreign/testStarted', {
method: 'post',
params,
})
在项目里有个api文件里面的内容是这样子,首先我不是说这种写发错误哈,你的代码你爱怎么写怎么写,我就是发表一下自己的看法(别杠,杠就是你赢)
所以对于这种情况我就想问,拆分出api这个文件的意义何在?
众所周知封装的意义是为了复用一段逻辑或者一个组件等,像上面的api只是传递了一下,但实际没做任何处理,这样的封装即使一千层也不解决问题,所以在我看来就是无意义的封装。
但你可能会说这样写方便以后接口的管理,对此我想结合实际情况说一下,在一个项目里接口改动的次数会有几次,而且还是直接这种 /api/getData 变成 /api/getMessage 需要你去改下接口”单词”的情况,当然也不能排除会有,于是我现在的封装方法是:
// 同样是api文件
const env = import.meta.env //vite中环境变量的引入
let busUrl = '/api-test';
if (env.MODE === "production") {
busUrl = '/v4app/api';
}
const api = {
login: `${busUrl}/auth/login`, //登录
codeImg: `${busUrl}/code`, //登录页验证码
//......
//......其他接口api
}
export default api;
//所以现在使用时变成了(已经在main.js中全局引入了)
this.ajax({
url: this.api.login,
data: {
user: 'admin',
password: '123456'
},
method: 'post'
}).then((res)=>{
console.log('res--', res)
})
其实就只是把api接口给单独整合到了一个文件里,这样既方便以后针对接口的修改等问题,也少了上面那样冗余的封装。当需要改api接口时就在api文件改就可以,在具体业务逻辑改动就在具体ajax代码里改
以上就是我对http请求封装的部分理解,若有问题希望大佬们帮忙指正