如下,请求可以分为三部分
1.index.js中封装各类的请求,如get,post,put,delete,upload,login,logout,refresh等等请求。
2.request.js是创建一个axios赋予基础参数,并且添加响应拦截器。
3.requestUrl.js是用来抽取一个基础的url参数,并且做一个拼接。
下面按照这三个文件的引用顺序做一个单个文件的代码拆分分析
requestUrl.js
/**
* 请求地址统一处理/组装
* @param {*} actionName action方法名称
*/
export default function(actionName) {
let url = process.env.VUE_APP_BASE_URL || "http://***.com"
return url + actionName
}
request.js
/* jshint esversion: 6 */
import axios from "axios";
import Vue from "vue";
import router from "../router/index";
import store from "../store";
import requestUrl from "./requestUrl";
// 创建axios实例
const request = axios.create({
timeout: 10000 * 10,
});
// response拦截器
request.interceptors.response.use(
(response) => {
// 101 用户名或密码错误
// 102 REFRESH-TOKEN不存在/失效
// 103 token验证失败
// 104 未登录
let code = response.data.code;
if(code == 102 || (!store.state.refreshing && code == 104)){
// 退出登陆
store.commit("logout");
router.replace({ name: "login" });
}
if (!store.state.refreshing && code == 103) {
// token失效 刷新token
Vue.prototype.ajax.refresh();
response.data.msg = "长时间页面未更新,尝试重新提交或刷新页面";
}
return response.data;
},
(error) => {
return Promise.reject(error);
}
);
export { request, requestUrl };
index.js
1.里面需要引入的模块如下
import { request, requestUrl } from "./request";
import store from "../store/index";
import Vue from "vue";
import qs from "qs";
2.需要一个公共axios请求方法
/**
* axios请求封装
* @param {*} opt
*/
function send(opt, resolve, reject, success, error, complete) {
// 获取refresh_token时,延迟请求
if (store.state.refreshing) {
setTimeout(() => {
send(opt, resolve, reject, success, error, complete);
}, 300);
return;
}
let nowtime = new Date().getTime() / 1000;
//overtime是登录成功之后端返回的时间加上登录的时间戳
let overtime = Number(store.state.overtime);
// 如果登陆时间大于8小时则直接退出
if (store.state.token && overtime && nowtime - overtime > 8 * 3600) {
store.commit("logout");
router.replace({ name: "login" });
return;
}
// 如果登陆时间小于8小时并且超出refreshtoken时间,则刷新token
if (store.state.token && overtime && overtime < nowtime) {
store.commit("changeRefresh", false);//改变store.state.refreshComplate
ajax.refresh(opt, resolve, reject, success, error, complete);
return;
}
if (store.state.refreshComplate) {
let token = store.state.token;
if (token) {
opt.headers.token = token;
}
}
request(opt)
.then((res) => {
resolve(res);
if (success) success(res);
})
.catch((err) => {
reject(err);
if (error) error();
Vue.prototype.$message.error("网络错误,请稍后重试");
})
.finally(() => {
if (complete) complete();
});
}
3.需要封装一个拿取token的方法
function getToken() {
let token = store.state.token;
if (!token) {
store.commit("logout");
Vue.prototype.$message.error("登陆信息失效,请重新登陆");
router.replace({ name: "login" });
}
return token;
}
4.定义一个ajax对象在里面封装各种类型的方法,并且导出它
const ajax = {
get(){},
post(){},
put(){},
delete(){},
upload(){},
login(){},
logout(){},
refresh(){},
};
export { ajax };
get方法的封装
const ajax = {
get: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "get",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
params,
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
}
}
post方法的封装
const ajax = {
post: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
data: qs.stringify(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
put方法的封装
const ajax = {
put: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "put",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
data: qs.stringify(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
delete方法的封装
const ajax = {
delete: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "delete",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
params,
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
upload方法的封装
const ajax = {
upload: (url, params) => {
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl(url),
method: "post",
headers: {
"Content-Type": "multipart/form-data",
token,
},
data: toFormData(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
login方法的封装
const ajax = {
login: (params) => {
store.commit("isRefresh", false);
let opt = {
url: requestUrl("/login"),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify(params),
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject);
});
},
}
logout方法的封装
const ajax = {
logout: () => {
store.commit("isRefresh", false);
let token = getToken();
if (!token) return;
let opt = {
url: requestUrl("/logout"),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
token,
},
};
return new Promise((resolve, reject) => {
send(opt, resolve, reject, false, false, () => {
store.commit("logout");
});
});
},
}
refresh方法的封装
const ajax = {
refresh: (...success) => {
if (store.state.refreshing) return;
store.commit("isRefresh", true);
let opt = {
url: requestUrl("/refresh_token"),
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"refresh-token": store.state.refresh_token,
},
};
return new Promise((resolve, reject) => {
request(opt)
.then((res) => {
resolve(res);
if (res.code == 0) {
store.commit("setUserInfo", res.data);
if (success) {
if (success[0].headers && success[0].headers.token) {
success[0].headers.token = res.data.token;
}
send(...success);
}
}else{
ajax.logout()
}
})
.catch((err) => {
reject();
Vue.prototype.$message.error("网络错误,请稍后重试");
})
.finally(() => {
store.commit("isRefresh", false);
});
});
},
}