前言
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")

超时时间设置过长,则不会影响接口调用。



















