如果使用Array,存在并发操作Array的情况, Array很难处理并发操作.
Set和Map天然支持并发!
Set相比Array优点, 用值删除而非索引
Map相比Array优点,用key删除,同时查找和删除的效率优于Array
下边例子我只处理了相同requestUrl的情况,没有继续判断data和params的原因是我担心增加data和params作为Map的key,会造成key长度过长,但经过网上查找,似乎js对Map单个key的长度并没有要求! 但总要有一个极限?
const tasksMap = new Map()
const service = axios.create({
baseURL: config.serverUrl,
timeout: 30000,
validateStatus: function (status) {
return status >= 200 && status < 300
}
})
// request interceptor
service.interceptors.request.use(
(config) => {
const token = getToken()
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
debounceRequest(config)
return config
},
(error) => {
return Promise.reject(error)
}
)
service.interceptors.response.use((response) => {
if(response.config.isDebounce) {
tasksMap.delete(response.config.url)
}
return response.data
})
/**
* 目前只简单校验requestUrl是否重复,没有校验data和params
* @param {} config
* @returns
*/
const debounceRequest = (config) => {
const { isDebounce } = config
if(!isDebounce) return
config.requestStartTime = Date.now()
const record = tasksMap.get(config.url)
if(record) {
if(Date.now() - record.requestStartTime < config.timeout) {
console.warn('Request is debounced:', record.url)
throw new Error('Request cancelled');
} else {
// 已超时, 应对断网时请求一直未出队的情况
tasksMap.delete(config.url)
tasksMap.set(config.url, config)
}
} else {
tasksMap.set(config.url, config)
}
}
export default service