Vue3+Ts封装axios
封装思路
index.ts
我们需要在src的根⽬录下创建⼀个axios⽂件夹,其中创建⼀个index.ts⽂件,这个⽂件主要⽤来封装axios的配置(实例化请求配置、请求、相应)及相应的⽅法(登录跳转、消息提⽰、错误处理等)
base.ts
这个⽂件主要⽤于项⽬扩展的情况下不同模块需要调⽤不同接⼝(请求的base地址 baseURL )⽽前期做的准备,便于后期的维护
request.ts
主要⽤于封装基于axios配置的get/post/put/delete等使⽤⽅法。
api.ts
在后⾯的 main.ts 中引⼊该模块,包括所有接⼝数据信息写⼊该⽂件中。
index.ts
封装如下。考虑到单⼀职责,index这块只封装axios
// index.ts
import axios, { AxiosRequestConfig, Method } from "axios";
import router from "@/router";
import store from "@/store";
import { message } from 'ant-design-vue'
import { storage } from "../storage/storage";
import { dataList } from "@/components/aspin/data";
/**
* 跳转登录页
* 携带当前页⾯路由,以期在登录页⾯完成登录后返回当前页⾯
*/
const toLogin = () => {
name: 'LoginPage',
});
}
/**
* 请求失败后的错误统⼀处理
* @param {Number} status 请求失败的状态码
*/
const errorHandle = (status: number, other: string) => {
// 状态码判断
switch (status) {
case 302: ('接⼝重定向了!');
break;
case 400:
<("发出的请求有错误,服务器没有进⾏新建或修改数据的操作==>" + status)
break;
// 401: 未登录
// 未登录则跳转登录页⾯,并携带当前页⾯的路径
/
/ 在登录成功后返回当前页⾯,这⼀步需要在登录页操作。
case 401: //重定向
<("token:登录失效==>" + status + ":" + store.state.Roles)
<(store.state.Roles)
path: '/Login',
});
break;
// 403 token过期
// 清除token并跳转登录页
case 403:
<("登录过期,⽤户得到授权,但是访问是被禁⽌的==>" + status)
// storemit('token', null);
setTimeout(() => {
path: '/Login',
});
}, 1000);
break;
case 404:
<("⽹络请求不存在==>" + status)
break;
case 406:
<("请求的格式不可得==>" + status)
break;
case 408: (" 请求超时!")
break;
case 410:
<("请求的资源被永久删除,且不会再得到的==>" + status)
break;
case 422:
<("当创建⼀个对象时,发⽣⼀个验证错误==>" + status)
break;
case 500:
<("服务器发⽣错误,请检查服务器==>" + status)
case 502:
<("⽹关错误==>" + status)
break;
case 503:
<("服务不可⽤,服务器暂时过载或维护==>" + status)
break;
case 504:
<("⽹关超时==>" + status)
break;
default:
<("其他错误错误==>" + status)
}
}
// 定义接⼝
interface PendingType {
url?: string;
method?: Method;
params: any;
data: any;
cancel: any;
}
// 取消重复请求
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;
// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
for (const key in pending) {
const item: number = +key;
const list: PendingType = pending[key];
// 当前请求在数组中存在时执⾏函数体
if (list.url === config.url && hod === hod && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {      // 执⾏取消操作
list.cancel('操作太频繁,请稍后再试');
// 从数组中移除记录
pending.splice(item, 1);
}
}
};
/* 实例化请求配置 */
const instance = ate({
headers: {
//php 的 post 传输请求头⼀定要这个不然报错接收不到值
"Content-Type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin-Type": '*'
},
// 请求时长
timeout: 1000 * 30,
// 请求的base地址 TODO:这块以后根据不同的模块调不同的api
baseURL: v.VUE_APP_API_URL,
//    ? "测试"
//    : "正式",
// 表⽰跨域请求时是否需要使⽤凭证
withCredentials: false,
})
/**
* 请求
* 每次请求前,如果存在token则在请求头中携带token
*/
quest.use(
config => {
removePending(config);
config.cancelToken = new CancelToken((c) => {
pending.push({ url: config.url, method: hod, params: config.params, data: config.data, cancel: c });
});
// 登录流程控制中,根据本地是否存在token判断⽤户的登录情况
// 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
// 后台根据携带的token判断⽤户的登录情况,并返回给我们对应的状态码
// ⽽后我们可以在响应中,根据状态码进⾏⼀些统⼀的操作。
// const token = ken;
// localStorage.setItem('token', token);
if ((store.state.Roles)) {
store.state.Roles
config.headers.Authorization = (store.state.Roles);
}
return config;
},
error => {
<(message);
ject(message);
}
)
// 响应
sponse.use(function (config) {
dataList.show = true
fig);
if (config.status === 200 || config.status === 204) {
setTimeout(() => {
dataList.show = false
}, 400)
solve(config);
} else {
ject(config);
}
// 请求失败
}, function (error) {
const { response } = error;
if (response) {
errorHandle(response.status, ssage);
// 超时重新请求
const config = fig;
// 全局的请求次数,请求的间隙
const [RETRY_COUNT, RETRY_DELAY] = [3, 1000];
if (config && RETRY_COUNT) {
// 设置⽤于跟踪重试计数的变量
config.__retryCount = config.__retryCount || 0;
// 检查是否已经把重试的总数⽤完
if (config.__retryCount >= RETRY_COUNT) {
ject(response || { message: ssage });
}
// 增加重试计数
config.__retryCount++;
// 创造新的Promise来处理指数后退
const backoff = new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, RETRY_DELAY || 1);
});
// instance重试请求的Promise
return backoff.then(() => {
return instance(config);
});
}
ject(response);
} else {
// 处理断⽹的情况
// eg:请求超时或断⽹时,更新state的network状态
// network状态在app.vue中控制着⼀个全局的断⽹提⽰组件的显⽰隐藏
// 后续增加断⽹情况下做的⼀些操作
storemit('networkState', false);
}
}
)
// 只需要考虑单⼀职责,这块只封装axios
export default instance
base.ts
区分每个模块的 baseUrl ⽅便后期维护管理
// base.ts
export class Base {
/* 公共模块 */
static env = v.NODE_ENV === "development"
"localhost:8087"
: "produceCommon(⽣产线地址)"
}
也可以直接在index.ts中设置这样就不需要base.ts
const instance = ate({
// 请求的base地址 TODO:这块以后根据不同的模块调不同的api
baseURL: v.VUE_APP_API_URL,
})
需要配置根⽬录
.env.development
vue json字符串转数组
NODE_ENV = 'development'
# VUE_APP_API_URL = 'localhost:5001/'
VUE_APP_API_URL = 'localhost:8087/'
.env.production
# ⽣产环境的请求接⼝
NODE_ENV = 'production'
VUE_APP_API_URL = '/'
request.ts
封装axios的get、post⽅法,其余关于接⼝调⽤的⽅法也可写⼊该⽂件中,便于管理。// request.ts
import axios from "./index";
import qs from "qs";
export class Request {
/
**
* get⽅法
* @param {string} url 路径
* @param {object} params 参数
*/
static get = (url: string, params?: any) => {
return new Promise((resolve, reject) => {
<(url, { params: params }).then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
})
}
static post = (url: string, params?: any) => {
return new Promise((resolve, reject) => {
axios.post(url, qs.stringify(params)).then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
})
}
}
api.ts
vue页⾯需要使⽤的api接⼝
// 其中使⽤ install 的⽬的在于 ts在main.ts中
// 不能通过Vue.prototype.$Api这个⽅式直接调⽤
//,在全局⽅法中会说到使⽤插件的⽅式去挂载。
// api.ts
import { Base } from "./base";
import { Request } from "./request";
class api {
/
* api接⼝模块 */
public static article = {
// 直接在index.ts中设置不需要Base模块
genre: () => ('/api/SnArticle/GetCountAsync'),
// 基于Base模块封装调⽤
genres: () => (`${v}/api/SnArticle/GetCountAsync`),  }
}
export {
api
}
index.vue
import { api } from '../../utils/api/api'
import { onMounted } from 'vue'
onMounted(async () => {
await QueryAll()
().then((res: any) => {
console.log('genre' + res.data)
})
s().then((res: any) => {
console.log('genres' + res.data)
})
})
参考

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。