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
|
/**
* get 请求
* @param url
* @param params
* @param isHandleError
* @param httpCustomerOpertion 使用者传递过来的参数, 用于以后的扩展用户自定义的行为
* {
* isHandleResult: boolen //是否需要处理错误结果 true 需要/false 不需要
* isShowLoading: boolen //是否需要显示loading动画
* customHead: object // 自定义的请求头
* timeout: int //自定义接口超时的时间
* }
* @returns {Promise}
*/
get(url, params = {}, httpCustomerOpertion = { isHandleResult: true, isShowLoading: true }) {
if (!httpCustomerOpertion.hasOwnProperty("isHandleResult")) {
httpCustomerOpertion.isHandleResult = true
}
if (!httpCustomerOpertion.hasOwnProperty("isShowLoading")) {
httpCustomerOpertion.isShowLoading = true
}
const method = "GET"
const fetchUrl = url + CommonTool.qs(params) // 将参数转化到url上
const fetchParams = Object.assign({}, { method }, this.getHeaders())
return HttpUtil.handleFetchData(fetchUrl, fetchParams, httpCustomerOpertion)
}
/**
* post 请求
* @param url
* @param params
* @param isHandleError
* @param httpCustomerOpertion 使用者传递过来的参数, 用于以后的扩展用户自定义的行为
* @returns {Promise}
*/
post(url, params = {}, httpCustomerOpertion = { isHandleResult: true, isShowLoading: true }) {
if (!httpCustomerOpertion.hasOwnProperty("isHandleResult")) {
httpCustomerOpertion.isHandleResult = true
}
if (!httpCustomerOpertion.hasOwnProperty("isShowLoading")) {
httpCustomerOpertion.isShowLoading = true
}
const method = "POST"
const body = JSON.stringify(params) // 将参数转化成JSON字符串
const fetchParams = Object.assign({}, { method, body }, this.getHeaders())
return HttpUtil.handleFetchData(url, fetchParams, httpCustomerOpertion)
}
/** * 发送fetch请求
* @param fetchUrl
* @param fetchParams
* @returns {Promise}
*/
static handleFetchData(fetchUrl, fetchParams, httpCustomerOpertion) { // 1. 处理的第一步
const { isShowLoading } = httpCustomerOpertion
if (isShowLoading) {
HttpUtil.showLoading()
}
httpCustomerOpertion.isFetched = false
httpCustomerOpertion.isAbort = false
// 处理自定义的请求头
if (httpCustomerOpertion.hasOwnProperty("customHead")) {
const { customHead } = httpCustomerOpertion
fetchParams.headers = Object.assign({}, fetchParams.headers, customHead)
} // 2. 对fetch请求再进行一次Promise的封装
const fetchPromise = new Promise((resolve, reject) => {
fetch(fetchUrl, fetchParams).then(
response => { // 3. 放弃迟到的响应
if (httpCustomerOpertion.isAbort) {
// 3. 请求超时后,放弃迟到的响应
return
}
if (isShowLoading) {
HttpUtil.hideLoading()
}
httpCustomerOpertion.isFetched = true
response.json().then(jsonBody => {
if (response.ok) { // 4. 统一处理返回结果
if (jsonBody.status === 5) {
// token失效,重新登录
CommonTool.turnToLogin()
} else if (jsonBody.status) {
// 业务逻辑报错, 不属于接口报错的范畴
reject(HttpUtil.handleFailedResult(jsonBody, httpCustomerOpertion))
} else {
resolve(HttpUtil.handleResult(jsonBody, httpCustomerOpertion))
}
} else { // 5. 接口状态判断
// http status header <200 || >299
let msg = "当前服务繁忙,请稍后再试"
if (response.status === 404) {
msg = "您访问的内容走丢了…"
}
Toast.info(msg, 2)
reject(HttpUtil.handleFailedResult({ fetchStatus: "error", netStatus: response.status, error: msg }, httpCustomerOpertion))
}
}).catch(e => {
const errMsg = e.name + " " + e.message
reject(HttpUtil.handleFailedResult({ fetchStatus: "error", error: errMsg, netStatus: response.status }, httpCustomerOpertion))
})
}
).catch(e => {
const errMsg = e.name + " " + e.message
// console.error('ERR:', fetchUrl, errMsg)
if (httpCustomerOpertion.isAbort) {
// 请求超时后,放弃迟到的响应
return
}
if (isShowLoading) {
HttpUtil.hideLoading()
}
httpCustomerOpertion.isFetched = true
httpCustomerOpertion.isHandleResult && Toast.info("网络开小差了,稍后再试吧", 2)
reject(HttpUtil.handleFailedResult({ fetchStatus: "error", error: errMsg }, httpCustomerOpertion))
})
})
return Promise.race([fetchPromise, HttpUtil.fetchTimeout(httpCustomerOpertion)])
}
/**
* 统一处理后台返回的结果, 包括业务逻辑报错的结果
* @param result
* ps: 通过 this.isHandleError 来判断是否需要有fetch方法来统一处理错误信息
*/
static handleResult(result, httpCustomerOpertion) {
if (result.status && httpCustomerOpertion.isHandleResult === true) {
const errMsg = result.msg || result.message || "服务器开小差了,稍后再试吧"
const errStr = `${errMsg}(${result.status})`
HttpUtil.hideLoading()
Toast.info(errStr, 2)
}
return result
}
/**
* 统一处fetch的异常, 不包括业务逻辑报错
* @param result
* ps: 通过 this.isHandleError 来判断是否需要有fetch方法来统一处理错误信息
*/
static handleFailedResult(result, httpCustomerOpertion) {
if (result.status && httpCustomerOpertion.isHandleResult === true) {
const errMsg = result.msg || result.message || "服务器开小差了,稍后再试吧"
const errStr = `${errMsg}(${result.status})`
HttpUtil.hideLoading()
Toast.info(errStr, 2)
}
const errorMsg = "Uncaught PromiseError: " + (result.netStatus || "") + " " + (result.error || result.msg || result.message || "")
return errorMsg
}
/**
* 控制Fetch请求是否超时
* @returns {Promise}
*/
static fetchTimeout(httpCustomerOpertion) {
const { isShowLoading } = httpCustomerOpertion
return new Promise((resolve, reject) => {
setTimeout(() => {
if (!httpCustomerOpertion.isFetched) {
// 还未收到响应,则开始超时逻辑,并标记fetch需要放弃
httpCustomerOpertion.isAbort = true
// console.error('ERR: 请求超时')
if (isShowLoading) {
HttpUtil.hideLoading()
}
Toast.info("网络开小差了,稍后再试吧", 2)
reject({ fetchStatus: "timeout" })
}
}, httpCustomerOpertion.timeout || timeout)
})
}
|