/**
* 需求: 当分页请求时, 当新的请求发出, 自动中断上一次的请求
*
* 使用 axios 的 cancelToken 来实现 <http://www.axios-js.com/zh-cn/docs/#取消>
*
* 每次请求根据请求的 config 的 url 和 method 生成一个 cancelToken, 并将对应的 cancel 方法存起来
* 当有同样的方法请求过来后, 通过 url 和 method 拿出 cancel 方法并调用
* 这样就可以取消前一次还没返回的相同请求, 页面也不会响应, 保证页面一段时间内只会响应最后一次重复请求
*/
import axios from 'axios'
const pending = new Map()
/**
* 添加请求进入pending队列
* @param {Object} config 请求的配置
*/
export const addPending = config => {
const url = [config.method, config.url].join('&')
config.cancelToken = new axios.CancelToken(cancel => {
if (!pending.has(url)) {
pending.set(url, cancel)
}
})
}
/**
* 从 pending 队列中移除请求
* @param {Object} config 请求的配置
*/
export const delPending = config => {
const url = [config.method, config.url].join('&')
// 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
if (pending.has(url)) {
const cancel = pending.get(url)
cancel(url)
pending.delete(url)
}
}
/**
* 清空 pending 队列中的所有请求
*/
export const clearPending = () => {
for (const [url, cancel] of pending) {
cancel(url)
}
pending.clear()
}
const http = axios.create()
axios.defaults.withCredentials = true
export const useCancelToken = axiosInstance => {
axiosInstance.interceptors.request.use(config => {
delPending(config)
addPending(config)
return config
})
axiosInstance.interceptors.response.use(response => {
delPending(response.config)
return response
})
}