安装axios

1
npm install axios

配置环境变量

1
2
# .env.development
VITE_BASE_URL=/api
1
2
# .env.production
VITE_BASE_URL=https://xxxx.xxx

修改vite配置

如果不跨域自动忽略这一步
vite.config.ts文件中添加如下代码

1
2
3
4
5
6
7
8
9
server:{
proxy:{
'/api':{
target: 'https://xxxx.xxx',// 后端接口地址
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}

封装axios

创建文件/src/server/index.ts,这个文件主要是用来封装axios的配置,请求拦截、响应拦截、错误处理、消息统一通知等方法
键入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import axios, {AxiosInstance} from "axios";
import router from "../router";

const instance:AxiosInstance = axios.create({
// 请求时长
timeout: 1000 * 30,
baseURL: import.meta.env.VITE_BASE_URL,
})
instance.interceptors.request.use(
config=>{
// 此处可以根据业务添加token等等等。。。
return config;
},
error => {
console.log(error.data.error.message);
return Promise.reject(error.data.error.message);
}
)


instance.interceptors.response.use(
(config)=>{
if (config.status === 200 || config.status === 204) {
return Promise.resolve(config.data);
} else {
return Promise.reject(config);
}
},
async (error)=>{
const { response } = error;
if (response) {
await errorHandle(response.status);
const config = error.config;
// 全局的请求次数,请求的间隙
const [RETRY_COUNT, RETRY_DELAY] = [3, 1000];
if (config && RETRY_COUNT) {
// 设置用于重试计数的变量
config.$retryCount = config.$retryCount || 0;
// 判断是不是用完请求的次数 总共发送请求的次数为RETRY_COUNT + 1 1为第一次发送的请求
if (config.$retryCount >= RETRY_COUNT) {
return Promise.reject(response || { message: error.message });
}
// 增加请求的次数
config.$retryCount++;
await delay(RETRY_DELAY || 1);
// 重新发起请求
return instance(config);
}
return Promise.reject(response);
}else {
console.log('这是断网了')
// 处理断网的情况
}
}
)

export default instance;

const delay = async (time:number)=>{
console.log(time);
return new Promise((resolve)=>{
setTimeout(() => {
resolve(undefined);
}, time || 1);
})
}
const errorHandle = async (status: number) => {
// 状态码判断
switch (status) {

case 302: console.log('接口重定向了!');
break;
case 400:
console.log("发出的请求有错误,服务器没有进行新建或修改数据的操作==>" + status)
break;
case 401: //重定向
// 此处应该清楚token
console.log("token:登录失效==>" + status)
await router.replace({
path: '/Login',
});
break;
// 403 token过期
// 清除token并跳转登录页
case 403:
console.log("登录过期,用户得到授权,但是访问是被禁止的==>" + status)
// store.commit('token', null);
setTimeout(() => {
router.replace({
path: '/Login',
});
}, 1000);
break;
case 404:
console.log("网络请求不存在==>" + status)
break;
case 406:
console.log("请求的格式不可得==>" + status)
break;
case 408: console.log(" 请求超时!")
break;
case 410:
console.log("请求的资源被永久删除,且不会再得到的==>" + status)
break;
case 422:
console.log("当创建一个对象时,发生一个验证错误==>" + status)
break;
case 500:
console.log("服务器发生错误,请检查服务器==>" + status)
break;
case 502:
console.log("网关错误==>" + status)
break;
case 503:
console.log("服务不可用,服务器暂时过载或维护==>" + status)
break;
case 504:
console.log("网关超时==>" + status)
break;
default:
console.log("其他错误错误==>" + status)
}
}

封装请求方式

创建文件/src/server/request.ts,封装常用的请求类型,这块只封装了postget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import axios from "./index";
export class Request {
static get = (url: string,params?:any) => {
return new Promise((resolve, reject) => {
axios.get(url, { params }).then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
})
}

static post = (url: string, data?: any,params?:any) => {
return new Promise((resolve, reject) => {
axios.post(url, data,{params}).then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
})
}
}

到目前为止就可以了,基本的请求已经,接下来就是按模块去处理接口了

封装接口地址

这块以用户模块为例
创建文件/API/User/index.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { Request } from "../../server/request.ts"
interface ILoginParams {
username:string;
password:string;
code:number
}
interface ICodeParams {
time:number
}
class User {
static login(data:ILoginParams){
return Request.post('/user/login',data);
}
static getCode(params:ICodeParams){
return Request.get('/user/verificationCode',params)
}
}
export default User;

如果接口不多,不需要按照模块去封装的话,也可以单独只写一个文件

1
2
3
4
5
6
7
8
class Api{
static login(data:ILoginParams){
return Request.post('/user/login',data);
}
static getCode(params:ICodeParams){
return Request.get('/user/verificationCode',params)
}
}

调用接口

1
2
3
4
5
6
7
8
import User from "../../Api/User";
User.getCode({
time:new Date().getTime()
}).then(res=>{
console.log(res);
}).catch(error=>{
console.log(error)
})