Vue实战@axios二次封装

概述

axios 二次封装的相关总结。配套测试源码

详述

基础实现

之所以需要二次封装,因为正常情况下,我们会针对错误之类的作统一处理,除了错误还有请求头,url 等,详细可参考 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
// utils>request.js
import axios from "axios";
import { notification } from "ant-design-vue";

function request(options) {
return axios(options)
.then(res => {
return res;
})
.catch(error => {
const {
response: { status, statusText }
} = error;
notification.error({
// jsx语法美化提示信息展示样式
message: h => (
<div>
请求错误 <span style="color: red">{status}</span> : {options.url}
</div>
),
description: statusText
});
return Promise.reject(error);
});
}

export default request;

特别提示

示例中 notification 的 message 部分使用了 jsx 语法,有关 vue 中使用 jsx 的方法如下:

  1. 首先需要安装@vue/babel-preset-jsx@vue/babel-helper-vue-jsx-merge-props
  2. 然后修改 babel 配置presets: ["@vue/app", "@vue/babel-preset-jsx"],
  3. 最后在 vue 组件中使用,如上示例代码 message 部分。

进阶实现

以下是摘自奇舞周刊公众号。

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
import axios from "axios";
import router from "../router";
import { MessageBox, Message } from "element-ui";
let loginUrl = "/login";
// 根据环境切换接口地址
axios.defaults.baseURL = process.env.VUE_APP_API;
axios.defaults.headers = { "X-Requested-With": "XMLHttpRequest" };
axios.defaults.timeout = 60000;
// 请求拦截器
axios.interceptors.request.use(
config => {
if (router.history.current.path !== loginUrl) {
let token = window.sessionStorage.getItem("token");
if (token == null) {
router.replace({
path: loginUrl,
query: { redirect: router.currentRoute.fullPath }
});
return false;
} else {
config.headers["Authorization"] = "JWT " + token;
}
}
return config;
},
error => {
Message.warning(error);
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
response => {
return response.data;
},
error => {
if (error.response !== undefined) {
switch (error.response.status) {
case 400:
MessageBox.alert(error.response.data);
break;
case 401:
if (window.sessionStorage.getItem("out") === null) {
window.sessionStorage.setItem("out", 1);
MessageBox.confirm("会话已失效! 请重新登录", "提示", {
confirmButtonText: "重新登录",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
router.replace({
path: loginUrl,
query: { redirect: router.currentRoute.fullPath }
});
})
.catch(action => {
window.sessionStorage.clear();
window.localStorage.clear();
});
}
break;
case 402:
MessageBox.confirm("登陆超时 !", "提示", {
confirmButtonText: "重新登录",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
router.replace({
path: loginUrl,
query: { redirect: router.currentRoute.fullPath }
});
});
break;
case 403:
MessageBox.alert("没有权限!");
break;
// ...忽略
default:
MessageBox.alert(`连接错误${error.response.status}`);
}
return Promise.resolve(error.response);
}
return Promise.resolve(error);
}
);
// 导出基础请求类型封装
export default {
get(url, param) {
if (param !== undefined) {
Object.assign(param, { _t: new Date().getTime() });
} else {
param = { _t: new Date().getTime() };
}
return new Promise((resolve, reject) => {
axios({ method: "get", url, params: param }).then(res => {
resolve(res);
});
});
},
getData(url, param) {
return new Promise((resolve, reject) => {
axios({ method: "get", url, params: param }).then(res => {
if (res.code === 4000) {
resolve(res.data);
} else {
Message.warning(res.msg);
}
});
});
},
post(url, param, config) {
return new Promise((resolve, reject) => {
axios.post(url, param, config).then(res => {
resolve(res);
});
});
},
put: axios.put,
_delete: axios.delete
};

参考

极客时间——Vue 开发实战

奇舞周刊