最近做项目遇到一个需求,需要在切换路由时,取消当前所有未完成的请求,隐约记得axios中有cancelToken这么一个东东(https://github.com/axios/axios),二话不说就是干,axios文档如下:
从文档中可知,有两种取消请求的方法,另外还声明可以使用同一个cancel token取消多个请求。于是我就照猫画虎,写出下列代码:
// 配置请求
const CancelToken = axios.CancelToken
const source = CancelToken.source()
store.requestCancel = source.cancel // 保存到全局变量,用于路由切换时调用
const http = axios.create({
cancelToken: source.token
})
// 路由切换
router.beforeEach((to, from, next) => {
store.requestCancel && store.requestCancel()
next()
})
心里想着,每个请求都会带上cancelToken,每次切换路由时,在跳转前执行取消请求的操作,完美!!crtl+s, npm start,切换路由,what???切换后的页面请求怎么拿不到数据?各种debugger一调,怎么切换路由后的请求response都没有执行,直接就到catch了?打开Network,显示请求也没有发送,难道执行了cancel函数后,所有的请求都不发送了吗?查看axios源码发现,在lib/adapters/http.js中存在一段代码如下:
if (config.cancelToken) {
config.cancelToken.promise.then(functiion onCanceled(cancel) {
if (aborted) {
return;
}
req.abort();
reject(cancel);
aborted = true
});
}
大致的意思就是说如果请求的配置中存在cancelToken,并且该cancelToken中存在promise的话就执行then方法,由于在上述代码中,在切换路由前执行了source.cancel方法,并且在所有的请求中配置的是同一个cancelToken,所以在之后的所有请求都会直接执行onCanceled方法,从而abort请求。
知道了缘由,接下来的工作就很简单啦,直接上修改后的代码:
// 配置发送请求拦截器
http.interceptors.request.use(config => {
config.cancelToken = store.source.token
return config
}, err => {
return Promise.reject(err)
})
router.beforeEach((to, from, next) => {
const CancelToken = axios.CancelToken
store.source.cancel && store.source.cancel()
store.source = CancelToken.source()
next()
})
// 全局变量
store = {
source: {
token: null,
cancel: null
}
}
先后的变化就是每次路由变化前,执行cancel方法并且更新cancelToken。
初次写文章,请多指教!!