Vue组件销毁时怎么正确取消Axios请求?请求还是在后台执行了
在做商品列表页的时候,当快速切换路由时,之前的Ajax请求还在后台完成了,导致新页面的数据被旧数据覆盖。我试过在beforeDestroy里调用cancel函数,但控制台还是报错说响应拦截器被调用了。
我用了axios的CancelToken,代码大概是这样的:
this.source = axios.CancelToken.source();
axios.get('/api/products', {
cancelToken: this.source.token
}).then(res => {
this.products = res.data;
});
beforeDestroy() {
this.source.cancel('组件销毁');
}
可是当我在路由切换时,虽然控制台能看到”取消错误”,但后端返回的数据还是触发了.then里的代码,把新页面的数据给覆盖了。难道cancel只是阻止了Promise状态更新?有没有更好的办法彻底终止请求?
另外页面有个加载动画的CSS:
.loading {
opacity: 0;
transition: opacity 0.3s;
&.active {
opacity: 1;
}
}
这个动画在请求取消后还是会执行完过渡效果,感觉和请求状态不一致。
解决办法是,在每个请求的 catch 中判断是否是主动取消的错误,并阻止后续逻辑。代码可以这么改:
至于加载动画的问题,可以在取消请求时同步移除动画状态。比如在 catch 里手动关闭动画标志位:
差不多就这样,记得处理好 Promise 的 rejected 状态就行。
cancel只是阻止了 Promise 的正常状态变化,但回调还是可能执行。建议在请求前先判断是否已经取消:至于加载动画的问题,可以在
beforeDestroy里直接移除.active类或者重置样式,应该能用。