vue-axios-optimize 1.0.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +192 -286
- package/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# vue-axios-optimize使用说明
|
|
2
2
|
|
|
3
|
-
vue-axios-optimize是一个对axios请求优化的vue
|
|
3
|
+
vue-axios-optimize是一个对axios请求优化的vue插件包,引入此包之后,并进行相关配置,即可轻松实现全局请求加载动画,重复请求时取消前面的请求或者阻止后面的请求,并且可实现请求并发数量控制。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -28,159 +28,146 @@ api目录大致如下
|
|
|
28
28
|
> > >
|
|
29
29
|
> > > axios-optimize.js
|
|
30
30
|
|
|
31
|
-
axios-optimize.js文件内容大致如下
|
|
31
|
+
**无配置无感知刷新token时** axios-optimize.js文件内容大致如下
|
|
32
32
|
|
|
33
33
|
```js
|
|
34
|
-
import axios from
|
|
35
|
-
import instance from
|
|
34
|
+
import axios from "axios"
|
|
35
|
+
import instance from "@/api/axios"
|
|
36
|
+
import axiosOptimize from "vue-axios-optimize"
|
|
37
|
+
import store from "@/store"
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
const AxiosOptimize = new axiosOptimize(axios, instance, {
|
|
40
|
+
responseTypesStr: "arraybuffer,blob", // 当axios请求设置 responseType为arraybuffer或blob时,直接返回原始数据
|
|
41
|
+
showLoadingFun: (config, requestingNum) => { // 当需要加载动画的请求数量不为0时的回调函数
|
|
42
|
+
store.commit("app/SET_LOADING_STATUS", true)
|
|
43
|
+
},
|
|
44
|
+
hideLoadingFun: (config, requestingNum) => { // 当需要加载动画的请求数量为0时的回调函数
|
|
45
|
+
store.commit("app/SET_LOADING_STATUS", false)
|
|
46
|
+
},
|
|
47
|
+
responseResultFun: (res) => { // 相应数据格式化
|
|
48
|
+
return res.data // 业务上希望用到的数据
|
|
49
|
+
}
|
|
50
|
+
})
|
|
40
51
|
|
|
41
|
-
|
|
52
|
+
export default AxiosOptimize
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**配置无感知刷新token时** axios-optimize.js文件内容大致如下
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
```js
|
|
58
|
+
import axios from "axios"
|
|
59
|
+
import instance from "@/api/axios"
|
|
60
|
+
import axiosOptimize from "vue-axios-optimize"
|
|
61
|
+
import store from "@/store"
|
|
62
|
+
import {MessageBox} from "element-ui"
|
|
44
63
|
|
|
45
64
|
const AxiosOptimize = new axiosOptimize(axios, instance, {
|
|
46
|
-
responseTypesStr: "arraybuffer,blob",
|
|
47
|
-
showLoadingFun: () => {
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
responseTypesStr: "arraybuffer,blob", // 当axios请求设置 responseType为arraybuffer或blob时,直接返回原始数据
|
|
66
|
+
showLoadingFun: (config, requestingNum) => { // 当需要加载动画的请求数量不为0时的回调函数
|
|
67
|
+
store.commit("app/SET_LOADING_STATUS", true)
|
|
68
|
+
},
|
|
69
|
+
hideLoadingFun: (config, requestingNum) => { // 当需要加载动画的请求数量为0时的回调函数
|
|
70
|
+
store.commit("app/SET_LOADING_STATUS", false)
|
|
71
|
+
},
|
|
72
|
+
openRefresh: true, // 启用无感知刷新token的开关
|
|
73
|
+
responseResultFun: (res) => { // 相应数据格式化
|
|
74
|
+
return res.data
|
|
50
75
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
76
|
+
refreshApiUrl: "/xiaobuAdmin/refreshToken", // 刷新tokenApi的 url
|
|
77
|
+
getRefreshTokenFun: () => { // 获取refreshToken的方法
|
|
78
|
+
return store.getters.refreshToken
|
|
54
79
|
},
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
getRefreshTokenFun: () => {
|
|
58
|
-
const useUserStore = useUserStoreHook()
|
|
59
|
-
// 获取refreshToken
|
|
60
|
-
return useUserStore.gettersRefreshToken
|
|
80
|
+
refreshTokenStore: (refreshToken) => { // 调用刷新token的方法 并将获取到的数据存储到cookie 及axios.js用到token的地方
|
|
81
|
+
return store.dispatch("user/refreshToken", refreshToken)
|
|
61
82
|
},
|
|
62
|
-
reloginFun: async
|
|
63
|
-
// 重新登录方法
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
await useUserStore.clearAuth()
|
|
67
|
-
ElMessageBox.alert(`${response.message}`, '提示', {
|
|
68
|
-
confirmButtonText: 'OK',
|
|
83
|
+
reloginFun: async(response) => {
|
|
84
|
+
// 重新登录方法 弹框提示 点击确认后 建议清除 缓存中token等信息后 刷新页面
|
|
85
|
+
MessageBox.alert(`${response.message}`, "提示", {
|
|
86
|
+
confirmButtonText: "OK",
|
|
69
87
|
showClose: false,
|
|
70
|
-
callback: async
|
|
71
|
-
if (action ===
|
|
88
|
+
callback: async(action) => {
|
|
89
|
+
if (action === "confirm") {
|
|
90
|
+
// 清除缓存中的token等信息
|
|
91
|
+
store.commit("user/CLEAR_AUTH")
|
|
72
92
|
// 刷新浏览器是为了 跳转登录页时query的redirect 会带上 当前页面地址(路由拦截处的逻辑)
|
|
73
93
|
window.location.reload()
|
|
74
94
|
}
|
|
75
95
|
}
|
|
76
96
|
})
|
|
77
|
-
},
|
|
78
|
-
refreshTokenStore: (refreshToken) => {
|
|
79
|
-
// 使用refreshToken 调用刷新token接口 获取新的accessToken 并存储到对应缓存中 使接口能用
|
|
80
|
-
const useUserStore = useUserStoreHook()
|
|
81
|
-
// 调用store的获取refreshToken方法 同时会将新的accessToken存储到缓存
|
|
82
|
-
return useUserStore.refreshTokenAction({ refreshToken })
|
|
83
|
-
},
|
|
84
|
-
setAccessTokenFun: (config, accessToken) => {
|
|
85
|
-
// 根据需求给请求头设置 accessToken 如下两种形式可设置请求头 二选一
|
|
86
|
-
// Reflect.set(config.headers, 'authorization', 'Bearer ' + accessToken)
|
|
87
|
-
config.headers.authorization = 'Bearer ' + accessToken
|
|
88
|
-
},
|
|
89
|
-
responseResultFun: (res) => {
|
|
90
|
-
/*res数据结构大致如下: 为接口返回的最外层数据 加个 请求时的config
|
|
91
|
-
{
|
|
92
|
-
code: 200,
|
|
93
|
-
data: XXX,
|
|
94
|
-
message: XXX,
|
|
95
|
-
config: {}
|
|
96
|
-
}
|
|
97
|
-
*/
|
|
98
|
-
// 此方法配置 返回数据 的 逻辑
|
|
99
|
-
if (res.config.responesType === 'blob') {
|
|
100
|
-
delete res.config
|
|
101
|
-
return res
|
|
102
|
-
}
|
|
103
|
-
if (res.code === 200) {
|
|
104
|
-
return res.data
|
|
105
|
-
}
|
|
106
|
-
delete res.config
|
|
107
|
-
return res
|
|
108
|
-
},
|
|
109
|
-
formatAccessToken: (data) => {
|
|
110
|
-
// 此方法返回 请求接口后 返回的 accessToken
|
|
111
|
-
return data.accessToken
|
|
112
97
|
}
|
|
113
98
|
})
|
|
114
99
|
|
|
115
|
-
export default AxiosOptimize
|
|
100
|
+
export default AxiosOptimize
|
|
116
101
|
```
|
|
117
102
|
|
|
103
|
+
|
|
104
|
+
|
|
118
105
|
axios.js的内容需要做些细微的更改 大致内容如下
|
|
119
106
|
|
|
120
107
|
```js
|
|
121
|
-
import axios from
|
|
122
|
-
import
|
|
123
|
-
import
|
|
108
|
+
import axios from "axios"
|
|
109
|
+
import Message from "@/plugins/reset-message.js"
|
|
110
|
+
import store from "@/store"
|
|
124
111
|
|
|
125
112
|
// 创建axios实例
|
|
126
113
|
const service = axios.create({
|
|
127
|
-
baseURL:
|
|
128
|
-
timeout:
|
|
114
|
+
baseURL: window.configObj.baseUrl || process.env.VUE_APP_BASE_URL,
|
|
115
|
+
timeout: window.configObj.timeout || process.env.VUE_APP_TIME_OUT // 请求超时时间
|
|
129
116
|
})
|
|
130
117
|
|
|
131
118
|
// request拦截器
|
|
132
119
|
service.interceptors.request.use(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const useUserStore = useUserStoreHook()
|
|
136
|
-
const accessToken = useUserStore.gettersAccessToken
|
|
120
|
+
config => {
|
|
121
|
+
const accessToken = store.getters.accessToken
|
|
137
122
|
if (accessToken) {
|
|
138
|
-
config.headers
|
|
123
|
+
config.headers.Authorization = "Bearer " + accessToken
|
|
139
124
|
}
|
|
140
125
|
|
|
141
126
|
return config
|
|
142
127
|
},
|
|
143
|
-
|
|
144
|
-
// 这个return 一定记得 带上 否则无法使用
|
|
128
|
+
error => {
|
|
145
129
|
return Promise.reject(error)
|
|
146
130
|
}
|
|
147
131
|
)
|
|
148
132
|
|
|
149
133
|
// respone拦截器
|
|
150
134
|
service.interceptors.response.use(
|
|
151
|
-
async
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
135
|
+
async response => {
|
|
136
|
+
|
|
137
|
+
const {data, config, status, request} = response
|
|
138
|
+
// 如果自定义代码不是200,则判断为错误。
|
|
139
|
+
if (status !== 200) {
|
|
140
|
+
Message({
|
|
141
|
+
message: data.message || "Error",
|
|
142
|
+
type: "error",
|
|
143
|
+
duration: 5 * 1000
|
|
144
|
+
})
|
|
145
|
+
return { ...data, config, responseErr: true}
|
|
146
|
+
} else {
|
|
147
|
+
// 二进制数据则直接返回
|
|
148
|
+
if (request.responseType === "blob" || request.responseType === "arraybuffer"){
|
|
149
|
+
return response
|
|
150
|
+
}
|
|
151
|
+
if (data.code === 200) {
|
|
152
|
+
return { ...data, config}
|
|
153
|
+
}
|
|
154
|
+
return { ...data, config, responseErr: true}
|
|
161
155
|
}
|
|
162
|
-
// 当项目无 无感知刷新token的功能时 此处对应code该什么逻辑就什么逻辑
|
|
163
|
-
// dosomething ... 如 code === 401 时 清除token 刷新页面等
|
|
164
|
-
|
|
165
|
-
// 报错时 多返回一个 报错标识 responseErr: true ...data 为接口返回的最外层数据
|
|
166
|
-
return { ...data, config, responseErr: true }
|
|
167
156
|
},
|
|
168
|
-
|
|
169
|
-
if (error.name ===
|
|
170
|
-
|
|
171
|
-
showClose: true,
|
|
172
|
-
message: `${error.message},请检查网络或联系管理员!`,
|
|
173
|
-
type: 'error'
|
|
174
|
-
})
|
|
157
|
+
error => {
|
|
158
|
+
if (error.name === "AxiosError") {
|
|
159
|
+
Message.error(error.message)
|
|
175
160
|
}
|
|
176
|
-
// 注意return 不可丢失
|
|
177
161
|
return Promise.reject(error)
|
|
178
162
|
}
|
|
179
163
|
)
|
|
180
164
|
|
|
181
165
|
export default service
|
|
166
|
+
|
|
182
167
|
```
|
|
183
168
|
|
|
169
|
+
|
|
170
|
+
|
|
184
171
|
接口处使用,如commo-api.js 大致如下
|
|
185
172
|
|
|
186
173
|
```js
|
|
@@ -190,113 +177,40 @@ import axiosOptimize from '@/api/axios-optimize.js'
|
|
|
190
177
|
// 需要配置 重复请求时 取消前面的请求 则 配置 preventDuplicateRequestsType: "cancel"
|
|
191
178
|
// 需要配置 重复请求时 禁用后面的请求 则 配置 preventDuplicateRequestsType: "prevent"
|
|
192
179
|
|
|
193
|
-
// get 请求demo
|
|
194
|
-
export function
|
|
180
|
+
// get 请求demo
|
|
181
|
+
export function getDemo(
|
|
195
182
|
data = {},
|
|
196
183
|
config = {
|
|
197
184
|
noShowLoading: true, // 配置不展示加载动画
|
|
198
185
|
preventDuplicateRequestsType: "cancel" // 配置重复请求时 取消前面的请求
|
|
199
186
|
}
|
|
200
187
|
) {
|
|
201
|
-
return axiosOptimize.get(`/xiaobu-admin/
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// get 请求 demo 2
|
|
205
|
-
export function getDemo2(
|
|
206
|
-
data = {},
|
|
207
|
-
config = {
|
|
208
|
-
preventDuplicateRequestsType: "prevent" // 配置重复请求时 后面的请求无效
|
|
209
|
-
}
|
|
210
|
-
) {
|
|
211
|
-
return axiosOptimize({
|
|
212
|
-
method: 'get',
|
|
213
|
-
url: `/xiaobu-admin/getDemo2`,
|
|
214
|
-
params: data,
|
|
215
|
-
...config
|
|
216
|
-
})
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// post 请求demo 1
|
|
220
|
-
export function postDemo1(data = {}, config = {}) {
|
|
221
|
-
return axiosOptimize.post('/xiaobu-admin/postDemo1', data, config)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// post 请求demo 2
|
|
225
|
-
export function postDemo2(data = {}, config: UserAxiosRequestConfig = {}) {
|
|
226
|
-
return axiosOptimize({
|
|
227
|
-
url: '/xiaobu-admin/postDemo2',
|
|
228
|
-
method: 'post',
|
|
229
|
-
data,
|
|
230
|
-
...config
|
|
231
|
-
})
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// delete 请求demo 1 使用params作为参数 参数会拼接在请求路径上
|
|
235
|
-
export function deleteDemo1(
|
|
236
|
-
data = {},
|
|
237
|
-
config = {
|
|
238
|
-
noShowLoading: true // 配置不展示加载动画
|
|
239
|
-
}
|
|
240
|
-
) {
|
|
241
|
-
return axiosOptimize.delete(`/xiaobu-admin/deleteDemo1`, { params: data, ...config })
|
|
188
|
+
return axiosOptimize.get(`/xiaobu-admin/getDemo`, { params: data, ...config })
|
|
242
189
|
}
|
|
243
190
|
|
|
244
|
-
//
|
|
245
|
-
export function
|
|
246
|
-
|
|
247
|
-
config = {}
|
|
248
|
-
) {
|
|
249
|
-
return axiosOptimize({
|
|
250
|
-
method: 'delete',
|
|
251
|
-
url: `/xiaobu-admin/deleteDemo2`,
|
|
252
|
-
params: data,
|
|
253
|
-
...config
|
|
254
|
-
})
|
|
191
|
+
// post 请求demo
|
|
192
|
+
export function postDemo(data = {}, config = {}) {
|
|
193
|
+
return axiosOptimize.post(`/xiaobu-admin/postDemo`, data, config)
|
|
255
194
|
}
|
|
256
195
|
|
|
257
|
-
// delete 请求
|
|
258
|
-
export function
|
|
259
|
-
return axiosOptimize.delete(`/xiaobu-admin/
|
|
196
|
+
// delete 请求demo1 使用data作为参数 参数不展示在 请求路径上
|
|
197
|
+
export function deleteDemo1(data = {}, config = {}) {
|
|
198
|
+
return axiosOptimize.delete(`/xiaobu-admin/deleteDemo1`, { data, ...config })
|
|
260
199
|
}
|
|
261
200
|
|
|
262
|
-
// delete 请求
|
|
263
|
-
export function
|
|
264
|
-
return axiosOptimize({
|
|
265
|
-
method: 'delete',
|
|
266
|
-
url: `/xiaobu-admin/deleteDemo4`,
|
|
267
|
-
data,
|
|
268
|
-
...config
|
|
269
|
-
})
|
|
201
|
+
// delete 请求demo2 使用params作为参数 参数展示在 请求路径上
|
|
202
|
+
export function deleteDemo2(data = {}, config = {}) {
|
|
203
|
+
return axiosOptimize.delete(`/xiaobu-admin/deleteDemo2`, { params: data, ...config })
|
|
270
204
|
}
|
|
271
205
|
|
|
272
|
-
// put 请求demo
|
|
206
|
+
// put 请求demo
|
|
273
207
|
export function putDemo1(data = {}, config = {}) {
|
|
274
|
-
return axiosOptimize.put(
|
|
208
|
+
return axiosOptimize.put(`/xiaobu-admin/putDemo`, data, config)
|
|
275
209
|
}
|
|
276
210
|
|
|
277
|
-
//
|
|
278
|
-
export function putDemo2(data = {}, config = {}) {
|
|
279
|
-
return axiosOptimize({
|
|
280
|
-
url: '/xiaobu-admin/putDemo2',
|
|
281
|
-
method: 'put',
|
|
282
|
-
data,
|
|
283
|
-
...config
|
|
284
|
-
})
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// patch 请求demo 1
|
|
211
|
+
// patch 请求demo
|
|
288
212
|
export function patchDemo1(data = {}, config = {}) {
|
|
289
|
-
return axiosOptimize.patch(
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// patch 请求demo 2
|
|
293
|
-
export function patchDemo2(data = {}, config = {}) {
|
|
294
|
-
return axiosOptimize({
|
|
295
|
-
url: '/xiaobu-admin/patchDemo2',
|
|
296
|
-
method: 'patch',
|
|
297
|
-
data,
|
|
298
|
-
...config
|
|
299
|
-
})
|
|
213
|
+
return axiosOptimize.patch(`/xiaobu-admin/patchDemo`, data, config)
|
|
300
214
|
}
|
|
301
215
|
|
|
302
216
|
```
|
|
@@ -311,109 +225,89 @@ export function patchDemo2(data = {}, config = {}) {
|
|
|
311
225
|
|
|
312
226
|
## options配置
|
|
313
227
|
|
|
314
|
-
| 参数
|
|
315
|
-
|
|
|
316
|
-
| showLoadingFun(config, requestingNum)
|
|
317
|
-
| hideLoadingFun(config, requestingNum)
|
|
318
|
-
| openRefresh
|
|
319
|
-
| refreshApiUrl
|
|
320
|
-
| getRefreshTokenFun()
|
|
321
|
-
| reloginFun(response)
|
|
322
|
-
| refreshTokenStore(refreshToken)
|
|
323
|
-
| setAccessTokenFun(config, accessToken)
|
|
324
|
-
| responseResultFun(res)
|
|
325
|
-
| formatAccessTokenFun(data) v1.0.6已废除
|
|
326
|
-
| accessTokenExpirationCode
|
|
327
|
-
| refreshTokenExpirationCode
|
|
328
|
-
| responseTypesStr(v1.0.2)
|
|
329
|
-
|
|
330
|
-
|
|
228
|
+
| 参数 | 类型 | 说明 | 是否必传 | 默认值 |
|
|
229
|
+
| -------------------------------------------------------- | -------- | ------------------------------------------------------------ | ------------------------- | ----------------------------------- |
|
|
230
|
+
| showLoadingFun(config, requestingNum) | Function | 展示动画,config为该请求的config,requestingNum为目前正在请求几个接口,此处可执行一些展示全局动画的操作 | 否 | 无 |
|
|
231
|
+
| hideLoadingFun(config, requestingNum) | Function | 隐藏动画,config为该请求的config,requestingNum为目前正在请求几个接口,此时应该为0,此处可执行关闭全局动画的操作 | 否 | 无 |
|
|
232
|
+
| openRefresh | Boolean | 是否开启无感知刷新token | 否 | false |
|
|
233
|
+
| refreshApiUrl | String | 请求刷新token接口的api地址 如/xiaobu-admin/refresh-token | 当openRefresh为true时必传 | 无 |
|
|
234
|
+
| getRefreshTokenFun() | Function | 获取当前项目的 refreshToken方法, 记得 return 回去 | 当openRefresh为true时必传 | 无 |
|
|
235
|
+
| reloginFun(response) | Function | response 为axios实例中返回的数据,此处建议执行清除token相关缓存并弹框提示,点击确认进行刷新页面操作 | 当openRefresh为true时必传 | 无 |
|
|
236
|
+
| refreshTokenStore(refreshToken) | Function | refreshToken为当前浏览器缓存的refreshToken,需要返回一个Promise,利用此refreshToken调用接口获取新的accessToken 并设置。v1.0.6及以上无需返回任何数据 | 当openRefresh为true时必传 | 无 |
|
|
237
|
+
| setAccessTokenFun(config, accessToken) (v1.0.8已废除) | Function | config为该请求的config,accessToken 为新获取的accessToken, 此处需要将accessToken设置到请求头中 | 当openRefresh为true时必传 | 无 |
|
|
238
|
+
| responseResultFun(res) | Function | res为axios实例返回的res,格式化接口请求成功后返回的数据 | 非必传 | axios实例返回的res |
|
|
239
|
+
| formatAccessTokenFun(data) v1.0.6已废除 | Function | data为responseResultFun报错时返回的res | 非必传 | axios实例返回的res.data.accessToken |
|
|
240
|
+
| accessTokenExpirationCode | number | 配置accessToken过期返回的业务状态码 | 非必传 | 401 |
|
|
241
|
+
| refreshTokenExpirationCode | number | 配置refreshToken过期返回的业务状态码 | 非必传 | 403 |
|
|
242
|
+
| responseTypesStr(v1.0.2) | String | 配置数据返回类型,实现当此类型时返回原封不动的响应数据的data数据 | 非必传 | 无 |
|
|
243
|
+
| maxReqNum (v2.0.0) | Number | 最大同时请求数量 | 非必传 | 4 |
|
|
244
|
+
|
|
245
|
+
## store/modules/user.js代码大致如下
|
|
331
246
|
|
|
332
247
|
```ts
|
|
333
|
-
import {
|
|
334
|
-
import {
|
|
335
|
-
import { commonApi } from '@/api'
|
|
336
|
-
import storage, { userKey } from '@/utils/storage'
|
|
337
|
-
import { setCookie, getCookie, removeCookie, accessTokenKey, refreshTokenKey } from '@/utils/cookie'
|
|
338
|
-
import { LoginVO, UserInfoVO, RefreshTokenVO } from '@/api/vo/common-vo'
|
|
339
|
-
import { RefreshTokenDTO } from '@/api/dto/common-dto'
|
|
340
|
-
const storageData = storage.info()
|
|
341
|
-
|
|
342
|
-
const useUserStore = defineStore('user', {
|
|
343
|
-
state: () => {
|
|
344
|
-
return {
|
|
345
|
-
accessToken: getCookie(accessTokenKey) || '',
|
|
346
|
-
refreshToken: getCookie(refreshTokenKey) || '',
|
|
347
|
-
userInfo: storageData[userKey] || null
|
|
348
|
-
}
|
|
349
|
-
},
|
|
248
|
+
import { setCookie, getCookie, removeCookie, accessTokenKey, refreshTokenKey } from "@/utils/cookie"
|
|
249
|
+
import { commonApi } from "@/api"
|
|
350
250
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
251
|
+
const getDefaultState = () => {
|
|
252
|
+
return {
|
|
253
|
+
accessToken: getCookie(accessTokenKey) || "", // 认证token
|
|
254
|
+
refreshToken: getCookie(refreshTokenKey) || "", // 刷新token
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const state = getDefaultState()
|
|
258
|
+
|
|
259
|
+
const mutations = {
|
|
260
|
+
// 重置初始化值
|
|
261
|
+
RESET_STATE: (state) => {
|
|
262
|
+
Object.assign(state, getDefaultState())
|
|
263
|
+
},
|
|
264
|
+
// 设置token
|
|
265
|
+
SET_TOKEN: (state, data) => {
|
|
266
|
+
const { accessToken, refreshToken, expiresIn} = data
|
|
267
|
+
state.accessToken = accessToken
|
|
268
|
+
setCookie(accessTokenKey, accessToken, expiresIn)
|
|
269
|
+
state.refreshToken = refreshToken
|
|
270
|
+
setCookie(refreshTokenKey, refreshToken, expiresIn)
|
|
361
271
|
},
|
|
362
272
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
},
|
|
371
|
-
// 清除AccessToken及RefreshToken
|
|
372
|
-
clearAuth() {
|
|
373
|
-
this.accessToken = ''
|
|
374
|
-
removeCookie(accessTokenKey)
|
|
375
|
-
this.refreshToken = ''
|
|
376
|
-
removeCookie(refreshTokenKey)
|
|
377
|
-
this.userInfo = null
|
|
378
|
-
storage.remove(userKey)
|
|
379
|
-
},
|
|
380
|
-
// 刷新token
|
|
381
|
-
async refreshTokenAction(params: RefreshTokenDTO) {
|
|
382
|
-
return new Promise<RefreshTokenVO>((resolve, reject) => {
|
|
383
|
-
commonApi
|
|
384
|
-
.refreshToken(params)
|
|
385
|
-
.then((data) => {
|
|
386
|
-
this.setToken(data)
|
|
387
|
-
resolve(data)
|
|
388
|
-
})
|
|
389
|
-
.catch((err) => {
|
|
390
|
-
reject(err)
|
|
391
|
-
})
|
|
392
|
-
})
|
|
393
|
-
},
|
|
394
|
-
|
|
395
|
-
// 获取用户信息
|
|
396
|
-
async getUserInfo() {
|
|
397
|
-
return new Promise<UserInfoVO>((resolve, reject) => {
|
|
398
|
-
commonApi
|
|
399
|
-
.getUserInfo()
|
|
400
|
-
.then((data) => {
|
|
401
|
-
this.userInfo = data
|
|
402
|
-
storage.set(userKey, data)
|
|
403
|
-
resolve(data)
|
|
404
|
-
})
|
|
405
|
-
.catch((err) => {
|
|
406
|
-
reject(err)
|
|
407
|
-
})
|
|
408
|
-
})
|
|
409
|
-
}
|
|
273
|
+
// 清除token 及其他可能影响操作的缓存数据
|
|
274
|
+
CLEAR_AUTH: (state) => {
|
|
275
|
+
state.accessToken = ""
|
|
276
|
+
removeCookie(accessTokenKey)
|
|
277
|
+
state.refreshToken = ""
|
|
278
|
+
removeCookie(refreshTokenKey)
|
|
279
|
+
// ...
|
|
410
280
|
}
|
|
411
|
-
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const actions = {
|
|
284
|
+
// 设置项目token
|
|
285
|
+
setToken({commit}, data) {
|
|
286
|
+
return new Promise((resolve, reject) => {
|
|
287
|
+
commit("SET_TOKEN", data)
|
|
288
|
+
resolve()
|
|
289
|
+
})
|
|
290
|
+
},
|
|
291
|
+
// 刷新token
|
|
292
|
+
refreshToken({commit}, refreshToken) {
|
|
293
|
+
return new Promise((resolve, reject) => {
|
|
294
|
+
commonApi.refreshToken({refreshToken}).then(data => {
|
|
295
|
+
commit("SET_TOKEN", data)
|
|
296
|
+
resolve()
|
|
297
|
+
})
|
|
298
|
+
})
|
|
299
|
+
},
|
|
300
|
+
}
|
|
412
301
|
|
|
413
|
-
export
|
|
414
|
-
|
|
302
|
+
export default {
|
|
303
|
+
namespaced: true,
|
|
304
|
+
state,
|
|
305
|
+
mutations,
|
|
306
|
+
actions
|
|
415
307
|
}
|
|
416
308
|
|
|
309
|
+
|
|
310
|
+
|
|
417
311
|
```
|
|
418
312
|
|
|
419
313
|
## 注意
|
|
@@ -456,7 +350,7 @@ module.exports = {
|
|
|
456
350
|
|
|
457
351
|
如有疑问,可关注微信公众号【爆米花小布】进行咨询。
|
|
458
352
|
|
|
459
|
-

|
|
460
354
|
|
|
461
355
|
微信公众号【爆米花小布】,抖音号【爆米花小布】 更多好玩的插件
|
|
462
356
|
|
|
@@ -471,6 +365,18 @@ module.exports = {
|
|
|
471
365
|
[vue2-water-marker水印插件](https://www.npmjs.com/package/vue2-water-marker)
|
|
472
366
|
|
|
473
367
|
## 更新日志
|
|
368
|
+
|
|
369
|
+
### 2.0.0
|
|
370
|
+
|
|
371
|
+
1. 【功能】实现并发请求数量控制,options新增maxReqNum参数配置 默认值为 4 ,表示同时可请求4个接口,剩余的接口陆续排队
|
|
372
|
+
2. 【优化】当接口返回数据格式为对象格式时,会多添加一个 IS_COMPLETE 表示当前全部请求任务是否已完成
|
|
373
|
+
3. 【调整】2.0.0版本 axios-optimize.js 文件不暴露 instance实例,且接口调用方法仅 支持 .get .post .delete .patch .put 形式调用, 具体查看文档示例
|
|
374
|
+
|
|
375
|
+
### 1.0.8
|
|
376
|
+
|
|
377
|
+
1. 【优化】废除options的setAccessTokenFun配置项
|
|
378
|
+
2. 【优化】将返回数据的config去除
|
|
379
|
+
|
|
474
380
|
### 1.0.6
|
|
475
381
|
|
|
476
382
|
1. 【优化】废除options的formatAccessTokenFun配置项
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{instance;requestObj={};requestingNum=0;authErrorArr=[];queue=[];isRefresh=!1;isShowReLoginDialog=!1;
|
|
1
|
+
class e{instance;requestObj={};requestingNum=0;authErrorArr=[];queue=[];isRefresh=!1;isShowReLoginDialog=!1;runningCount=0;maxReqNum=4;tasks=[];add(e){return new Promise(((t,s)=>{this.tasks.push({task:e,resolve:t,reject:s}),this._run()}))}_run(){for(;this.runningCount<this.maxReqNum&&this.tasks.length>0;){const{task:e,resolve:t,reject:s}=this.tasks.shift();this.runningCount++,e().then((e=>{this.runningCount--,"[object Object]"!==Object.prototype.toString.call(e)?t(e):t({...e,IS_COMPLETE:0===this.runningCount})})).catch((e=>{this.runningCount--,s(e)})).finally((()=>{this._run()}))}}get(e,t){const s=t.params;return delete t.params,this.add((()=>this.instance.request({url:e,params:s,...t,method:"GET"})))}post(e,t={},s={}){return this.add((()=>this.instance.request({url:e,data:t,...s,method:"POST"})))}delete(e,t={}){if(t.params){const s=t?.params||{};return delete t.params,this.add((()=>this.instance.request({url:e,params:s,...t,method:"DELETE"})))}const s=t?.data||{};return delete t.data,this.add((()=>this.instance.request({url:e,data:s,...t,method:"DELETE"})))}patch(e,t={},s={}){return this.add((()=>this.instance.request({url:e,data:t,...s,method:"PATCH"})))}put(e,t={},s={}){return this.add((()=>this.instance.request({url:e,data:t,...s,method:"PUT"})))}constructor(e,t,s){this.maxReqNum=s?.maxReqNum||this.maxReqNum,this.instance=t,this.instance.interceptors.request.use((t=>{t?.noShowLoading||(this.requestingNum++,s.showLoadingFun&&s.showLoadingFun(t,this.requestingNum));const r=t.url;if(s.openRefresh){-1===this.authErrorArr.indexOf(r)&&this.isRefresh&&r!==s.refreshApiUrl&&this.authErrorArr.push(r)}if(r&&t.preventDuplicateRequestsType)if("cancel"===t.preventDuplicateRequestsType){this.requestObj[r]&&this.requestObj[r].cancel({config:t,isCancel:!0});const s=e.CancelToken;this.requestObj[r]=s.source(),t.cancelToken=this.requestObj[r].token}else if("prevent"===t.preventDuplicateRequestsType){if("requesting"===this.requestObj[r])return Promise.reject({config:t,isPrevent:!0});this.requestObj[r]="requesting"}return t}),(e=>Promise.reject(e))),this.instance.interceptors.response.use((async e=>{const{config:t,responseErr:r}=e;if(t?.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},s.hideLoadingFun&&s.hideLoadingFun(t,this.requestingNum))),t&&this.requestObj[t.url]&&delete this.requestObj[t.url],r){if(s.openRefresh){const r=this.authErrorArr.indexOf(t.url);if(-1!==r)return this.authErrorArr.splice(r,1),new Promise((e=>{this.queue.push((()=>{e(this.instance.request(t))}))}));const i=s.accessTokenExpirationCode||401;if(Number(e.code)===i){const r=s.getRefreshTokenFun();if(!r){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,s.reloginFun(e),Promise.reject(new Error(e.message||"Error"))}if(this.isRefresh)return new Promise((e=>{this.queue.push((()=>{e(this.instance.request(t))}))}));this.isRefresh=!0;try{return await s.refreshTokenStore(r),this.queue.forEach((e=>e())),this.instance.request(t)}catch{if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,s.reloginFun(e),Promise.reject(new Error(e.message||"Error"))}finally{this.queue=[],this.isRefresh=!1}}const n=s.refreshTokenExpirationCode||403;if(Number(e.code)===n){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,s.reloginFun(e),Promise.reject(new Error(e.message||"Error"))}}return Promise.reject(new Error(e.message||"Error"))}if(s?.responseTypesStr?.toLocaleLowerCase().split(",").includes(t?.responseType?.toLocaleLowerCase()))return e.data;const i=JSON.parse(JSON.stringify(e));return delete i.responseErr,delete i.config,s.responseResultFun?s.responseResultFun(i):i}),(e=>{const t=e.config||e?.message?.config||{};return t?.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},s.hideLoadingFun&&s.hideLoadingFun(t,this.requestingNum))),e.isPrevent||e?.message?.isCancel||delete this.requestObj[t.url],Promise.reject(e)}))}}export default e;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-axios-optimize",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "vue项目对axios
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "vue项目对axios请求的优化,实现可配置展示全局加载动画,可配置是否重复请求时取消前面的请求或者阻止后面的请求,已经控制请求并发数量。",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
|