-
需要封装XMLHttpRequest
-
超时后执行 xhr.abort()
-
利用Promise.race得到http请求或者超时先回来
-
http请求先返回,那就终止setTimeout
-
超时先回来,那就终止http请求
// 带有超时的http请求
const isObject = v => v && typeof v == 'object'
const assert = (condition, msg) => {
if (!condition) throw new Error(msg)
}
function ajax(constroller, { method, url, param, data }) {
assert(url, 'url must not be empty!')
function createUrl() {
if (isObject(param)) {
param = Object.keys(param)
.map(key => {
return `${key}=${param[key]}`
})
.join('&')
}
if (!param) {
return url
}
url = url.toString().replace(/(\?+)$/g, '')
return param ? `${url}?${param}` : url
}
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
url = createUrl()
xhr.open(method, url, true)
xhr.onload = function () {
resolve(xhr.response)
}
constroller.abortHttp = () => xhr.abort()
xhr.onerror = function (error) {
reject(error)
}
xhr.send(data)
})
}
function timeout(constroller, timestamp = 0) {
if (timestamp <= 0) return
return new Promise((_, reject) => {
const timer = setTimeout(() => {
reject('timeout')
}, timestamp)
constroller.abortTime = () => {
clearTimeout(timer)
}
})
}
function AbortController() {
return {
abortHttp: null,
abortTime: null
}
}
function timeoutHttp(config) {
const constroller = new AbortController()
return Promise.race([
ajax(constroller, config),
timeout(constroller, config.timeout)
]).then(
function (res) {
constroller.abortTime()
return res
},
function (error) {
if (error == 'timeout') {
constroller.abortHttp()
}
return error
}
)
}
// 导出
export { timeoutHttp }