前言
Ajax
有两种方式实现请求,分别是xhr
和fetch
,前者有超时功能,fetch
则不然。下文尝试给fetch
添加超时功能。
实现
使用终止器
,在controller.abort()
时便会在使用其signal
信号的fetch
函数发送一个终止信号,请求就会被取消。
const controller = new AbortController()
fetch("https://xxx.com/aa/bb", {
signal: controller.signal,
})
setTimeout(() => {
console.log(controller)
controller.abort()
}, 10) // 这里10毫秒过于极端可能会导致不生效,具体根据使用场景设置
将超时时间设为较大值,则并不阻止请求。
封装
初步封装
const request = (timeout) => {
const controller = new AbortController()
fetch("https://xxx.com/aa/bb", {
signal: controller.signal,
})
setTimeout(() => {
controller.abort()
}, timeout)
}
但是会提高难度,明明只是要给fetch
加上超时功能,现在却变成封装请求,url、配置等都需要传递,duck不必,所以封装时一定要保证fetch
的功能不变,即用的时候和直接使用fetch是一样的。
参考MockJS
拦截Ajax
请求的做法,它获取原先的xhr,并给xhr重新赋值。
const oldXHR = XMLHttpRequest
window.XMLHttpRequest = function(){
// ...
new oldXHR()
}
但是也不能这么搞,这么做有侵入性
,会导致所有fetch
都带有超时功能。
使用高阶函数
则可以避免这种情况。
function createFetch(timeout) {
return (resource, options) => {
let controller = new AbortController()
options = options || {}
options.signal = controller.signal
setTimeout(() => {
controller.abort()
}, timeout)
return fetch(resource, options)
}
}
使用没有超时功能的fetch
fetch("https://xxx.com/aa/bb")
使用高阶函数
并传入超时时间:
createFetch(10)("https://xxx.com/aa/bb")
超时时间设置过长,则不会影响接口调用。