-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrequest.js
More file actions
205 lines (188 loc) · 6.82 KB
/
request.js
File metadata and controls
205 lines (188 loc) · 6.82 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import qs from 'qs'
// 同时支持promise和普通回掉函数的写法,防止重复,防重
(function ($) {
/**
* 阻止ajax重复提交,guid异步请求唯一标示符(如果config中有serialId字段则使用,否则使用url加)
* @param {JSON object} config 等同ajax中的config参数
* @return {[type]} [description]
*/
$.oneAjax = function (config) {
if (!config.url) {
throw new Error('提交的url不能为空')
}
let guid = config.serialId
if (!guid) {
let { url, data } = config
let params = qs.stringify(data)
guid = url + (typeof params === 'string' ? params : '')
}
if ($.oneAjax[guid] === true) {
return new Promise(function (resolve, reject) {
resolve({ code: 'serial-request', msg: '当前请求正在提交中,待请求返回后方可再次提交' })
})
}
$.oneAjax[guid] = true
return $.ajax(config).always(function () {
delete $.oneAjax[guid]
})
}
})(jQuery)
// 防重,防止重复提交axios
const http = {
// 防止重复提交
blockRequest: function (config) {
if (!config.url) {
throw new Error('提交的url不能为空')
}
let guid = config.serialId
if (!guid) {
let { url, params } = config
// console.log(params)
params = qs.stringify(params)
guid = url + (typeof params === 'string' ? params : '')
}
if (this.blockRequest[guid]) {
// 正在提交中
return new Promise((resolve, reject) => {
resolve({ code: 'serial-request', msg: '当前请求正在提交中,待请求返回后方可再次提交' })
})
}
this.blockRequest[guid] = true
// let self = this
return axios.request(config).finally(() => {
// 请求结束重置请求,以允许用户再次提交
// console.log('数据已经返回,重置请求状态标识符')
this.blockRequest[guid] = false
})
}
}
import axios from 'axios'
import type { AxiosRequestConfigPlus, RawAxiosRequestHeaders } from 'axios'
import env from '../../build/env.js'
// import { genCommonMessageOptions } from '@/utils/consts/config.js'
import { getToken, logoutClear } from '@/utils/auth.js'
import {
Message
} from 'element-ui'
// import router from '../router'
const requestLocker = new Map()
// 鉴权失效需要跳登录页http状态码
const authStatusCodes = [401, 403]
// create an axios instance
function getAxiosInstance (config) {
const headers = {
'Content-Type': 'application/json'
}
const service = axios.create({
baseURL: config.BASE_API || env[process.env.NODE_ENV].BASE_API, // api 的 base_url
timeout: 30000, // request timeout,
headers
})
// request interceptor
// 添加token,老版本接口请求体的data数据全部要系列化
service.interceptors.request.use(
config => {
config.headers.Authorization = getToken()
// config.withCredentials = true
config.data = JSON.stringify(config.data)
return config
},
error => {
// Do something with request error
// console.log('service.interceptors.request error', error) // for debug
Promise.reject(error)
}
)
// response interceptor
// 统一token失效处理,以及公共错误处理。
service.interceptors.response.use(
// response => response,
/**
* 根据状态码定义特殊提示
*/
response => {
// 如果是老调研家接口直接返回response,为了兼容老调研家api,如果v1Api方法被废弃则不需要再兼容
if (config.v1Api) {
return response
}
const { data } = response
const { code, message } = data
if (code === 200) {
// 兼容老接口,老接口可能会返回result字段, 后续会统一返回data,目前是为了兼容老接口
return data?.result ?? data
} else {
// 默认不显示统一错误处理
if (!config.hideError) Message.warning({
message,
showClose: true
})
return Promise.reject(message)
}
},
res => {
const status = res?.response?.status
let tipMsg
if (authStatusCodes.indexOf(status) !== -1) {
tipMsg = res?.response?.data?.message ?? '登录信息过期,请重新登陆'
logoutClear()
location.href = 'cem/login'
} else {
tipMsg = res?.response?.data?.message ?? '发生了一个网络错误'
}
// 默认不显示统一错误处理
if (!config.hideError) Message.warning({
message: tipMsg,
showClose: true
})
return Promise.reject(tipMsg)
}
)
return service
}
/**
* 封装Axios
* 1. 同一个url且参数也相同,则必须等到请求返回结果后才能提交,其他请求不受影响
* 2. 如果登录有token,则每个请求会在http header.Authorization中携带token
* 3. 设置一些基础默认参数,比如超时时间等
* 4. 统一错误处理,比如token失效调登录页
*/
export default function Request (config = {}) {
// 设置默认参数
config.method = config?.method ?? 'POST'
config.crossDomain = true
if (!config.url) {
throw new Error('提交的url不能为空')
}
let guid = config.serialId
if (!guid) {
let { url, params } = config
guid = url + JSON.stringify(params)
}
if (requestLocker.has(guid)) {
// 正在提交中
return new Promise((resolve, reject) => {
resolve({ code: 'serial-request', data: true, message: '当前请求正在提交中,待请求返回后方可再次提交' })
})
}
requestLocker.set(guid, true)
const service = getAxiosInstance(config)
return service.request(config).finally(() => {
// 请求结束重置请求,以允许用户再次提交, 防止内存泄露
requestLocker.delete(guid)
})
}
// 本来应该只有一个config参数
export function api (config: AxiosRequestConfigPlus) {
return Request(config)
}
export function get (config: AxiosRequestConfigPlus) {
return api({ ...config, method: 'GET' })
}
export function post (config: AxiosRequestConfigPlus) {
return api({ ...config, method: 'POST' })
}
// 下载
export function downloadByApi (config: AxiosRequestConfigPlus) {
config.responseType = 'blob'
return api(config)
}