Vue3.2+Vite2.x+Typescript项目进阶搭建-
2022-05-20 本文已影响0人
无我_无他_有你
axios模块的功能主体:对发起的请求做处理,对响应的请求做处理,对请求方式进行封装,对请求进行管理等等
vuex搭建(官方文档)
引入依赖
#axios依赖
npm install axios --save
#qs 依赖 (对请求传的参数转json字符串处理工具)
npm install qs --save
src下创建目录axios,axios目录下创建request.ts文件,内容如下(仅作参考)
import { message } from './../utils/resetMessage';
//引入 axios
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import qs from "qs";
import localStorageUtil from "/@utils/localStorageUtil";
import loadingUtil from "/@utils/loading";
import messageUtil from "/@utils/messageUtil";
import { ACCOUNT_SERVER } from "/@assets/constant/domain-name";
import router from "../router";
import { userStore } from "/@store/index";
const BASE_URL = "/api/" + ACCOUNT_SERVER;
// //允许跨域携带cookie信息 改配置与后端保持一致
axios.defaults.withCredentials = true;
// 设置重新请求次数
axios.defaults.retry = 10;
// 设置请求延时
axios.defaults.retryDelay = 1000;
// 接口类型和方法
interface BaseType {
baseURL: string;
getConfigParams(): any;
interceptors(instance: AxiosInstance, url: string | number | undefined): any;
request(options: AxiosRequestConfig): any;
}
interface AxiosRequestType {
baseURL?: string;
url?: string | undefined;
data?: any;
params?: any;
method?: string;
headers?: any;
timeout?: number;
value?: any;
cancelToken?: any;
}
// 取消重复请求
const CancelToken = axios.CancelToken;
// 用于存储每个请求的取消函数以及对应标识
let sources: any = [];
// 取消函数
let removeSource = (config: any) => {
for (let item in sources) {
if (sources[item].cancelFunction === config.url + "&" + config.method) {
sources[item].cancel("已取消重复请求,请勿重复请求");
sources.splice(item, 1);
}
}
};
let baseURL = import.meta.env.BASE_URL;
console.log("当前环境的基础路径为:" + baseURL);
class AxiosHttpRequest implements BaseType {
baseURL: string;
timeout: number;
constructor(baseURL: string, timeout: number) {
this.baseURL = import.meta.env.BASE_URL;
this.timeout = 10000;
}
// 配置参数
getConfigParams() {
const config = {
baseURL: this.baseURL,
timeout: this.timeout,
headers: {},
};
return config;
}
// 拦截设置
interceptors(config: AxiosInstance, url: string | number | undefined) {
// 请求拦截
config.interceptors.request.use(
(config: AxiosRequestType) => {
// 断网提示 李兰器不在线提示用户网络有问题
if (!navigator.onLine) {
messageUtil.warn("您的网络故障,请检查!");
return;
}
// 取消重复请求
removeSource(config);
config.cancelToken = new CancelToken((c) => {
// 将取消函数存起来
sources.push({
cancelFunction: config.url + "&" + config.method,
cancel: c,
});
});
// 添加全局的loading..
loadingUtil.show();
//全局参数统一处理
if (config.method === "post") {
config.data = qs.stringify({ ...config.data });
} else {
config.params = { ...config.params };
}
// 请求头携带token
// get请求映射params参数
if (config.method === "get" && config.params) {
let url = config.url + "?";
for (const propName of Object.keys(config.params)) {
const value = config.params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof value !== "undefined") {
if (typeof value === "object") {
for (const key of Object.keys(value)) {
let params = propName + "[" + key + "]";
var subPart = encodeURIComponent(params) + "=";
url += subPart + encodeURIComponent(value[key]) + "&";
}
} else {
url += part + encodeURIComponent(value) + "&";
}
}
}
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
//2.获取时间戳,精确到秒
let getTimestamp = Date.now().toString().substring(0, 10);
let url = config.url;
if (url) {
let indexOf = url.indexOf("?");
if (indexOf > -1) {
config.url = config.url + "×tamp=" + getTimestamp;
} else {
config.url = config.url + "?timestamp=" + getTimestamp;
}
}
if (config.headers) {
console.log("获取pinia中的token:" + userStore().getToken);
//3.添加请求头token
if (userStore().token && userStore().getToken != "") {
config.headers["Authentication"] = userStore().getToken;
} else {
//token 不存在跳转到登录页
router.replace("/login");
}
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
// 响应拦截
config.interceptors.response.use(
(res: any) => {
debugger;
// 取消重复请求
removeSource(res.config);
loadingUtil.hide();
// 获取错误信息
if (res.data.body) {
let errCode = res.data.body.errCode;
switch (errCode) {
//token失效重新获取token
case "A0225":
http
.get({
url: BASE_URL + "/token/refreshToken",
})
.then((res: any) => {
localStorageUtil.set("accessToken", res.data);
//重新发送请求 TODO
var config = res.config;
return axios(config);
});
break;
case "A0313":
messageUtil.error("权限不足,请联系管理员");
return Promise.reject(res);
}
} else {
return Promise.resolve(res);
}
},
(error: any) => {
debugger;
let msg: string;
if (error.response) {
let code: number = error.response.status;
switch (code) {
case 400:
msg = "错误请求";
break;
case 401:
msg = "认证信息已失效";
router.push("/login");
break;
case 403:
msg = "客户端非法请求";
break;
case 404:
msg = "访问资源不存在";
break;
case 405:
msg = "请求方式错误";
break;
case 500:
msg = "服务器内部异常";
break;
case 503:
msg = "服务不可用";
break;
case 504:
msg = "网络超时";
break;
case 505:
msg = "http版本不支持该请求";
break;
default:
msg = "未知错误,请联系管理员";
break;
}
} else {
msg = error.message;
if (msg == "Network Error") {
msg = "后端接口连接异常";
} else if (msg.includes("timeout")) {
msg = "系统接口请求超时";
} else if (msg.includes("Request failed with status code")) {
msg = "系统接口" + msg.substring(msg.length - 3) + "异常";
}
}
loadingUtil.hide();
messageUtil.error(msg);
return Promise.reject(error);
}
);
}
/**
* 外部调用方法
* @param options axios请求参数
* @returns 实例
*/
request(options: AxiosRequestConfig) {
const instance = axios.create();
options = Object.assign(this.getConfigParams(), options);
this.interceptors(instance, options.url);
return instance(options);
}
get<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "GET" });
}
post<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "POST" });
}
put<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "PUT" });
}
delete<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "DELETE" });
}
patch<T>(config: AxiosRequestConfig) {
return this.request({ ...config, method: "PATCH" });
}
}
// 实例化请求类
const http = new AxiosHttpRequest(baseURL, 3000);
export default http;
该过程是对请求动作,处理内容主要包括以下几方面
1.请求方式封装
2.重复请求过滤
3.请求头添加token
4.请求参数统一处理
5.请求拦截,对不需要权限的请求直接放行
6.对请求响应结果处理
7.请求重试
8.结合状态管理框架(vuex,pinia)处理用户权限信息等
api处理
src下创建目录 api 该目录用户存放调用接口方法,方便管理,文件内容示例:
import http from "../axios/request";
import globalConst from "/@constants/domain-name";
export function login(data: any) {
return http.post({
url: globalConst.account_server + "/user/login",
data,
});
}
export function logout(data: any) {
return http.post({
url: globalConst.account_server + "/user/logout",
data: data,
});
}
export function findById(id: number) {
return http.get({
url: globalConst.account_server + "/user/findUserById/",
params: { id: id },
});
}
export function getVerificationCode() {
return http.get({
url: globalConst.account_server + "/user/verifyCode",
responseType: "blob",
});
}
export function getUserMenuList() {
return http.get({
url: "/api/" + globalConst.auth_server + "/menu/tree",
});
}