这是我参与更文挑战的第6天,活动详情查看: 更文挑战
当切换步骤或切换tab等情况,前一个组件中发起的请求可能还在进行中,用户就已经退出了步骤流程,也可能是切换到了其他的tab页面,之前的请求还在进行中,如果不去处理未完成的请求,会极大地影响页面性能,甚至导致后续的请求超时,或者数据处理不正确,页面展示错误等等
对于以上类似的问题,我们就需要知道如何取消请求
官方示例
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// cancel the request
cancel();
复制代码
在请求配置之中实例化axios上的CancelToken方法,回调函数的返回值就是取消当前请求的方法:cancel,只需要把cancel保存到一个地方就可以随时调用,用来取消这个请求
在实际项目中我们往往不会像官网例子中那样使用,更多的是在axios的拦截器中做全局配置管理,需要对上面的代码进行一些改变
项目具体实现
项目中使用 Vuex 和 axios 请求和响应拦截器,在 axios 请求拦截器中实例化cancelToken然后把回调的取消请求方法,以请求的函数名为 key ,以取消请求的方法为 val ,注册到 Vuex 中,那么就可以在在这个请求周期内利用Vuex去调用这个方法,用来取消这个请求。
Vuex
store 文件夹中相关 modules 配置中增加 cancel 相关 state,actions 等
const state = {
cancel: {},
}
const mutations = {
CANCEL(state, { funNames = [], msg = "用户手动取消网络请求" }) {
if (!Object.keys(state.cancel).length) {
return false
}
for (const key in state.cancel) {
if (state.cancel.hasOwnProperty(key)) {
if (funNames.includes(key)) {
if (!state.cancel[key].response) {
state.cancel[key].cancel(msg);
state.cancel[key].response = true;
}
}
} else {
return false
}
}
},
SET_CANCEL(state, { cancel, funName }) {
state.cancel[funName] = { cancel, response: false };
},
RESPONSE(state, funName) {
if (Object.keys(state.cancel).includes(funName)) {
state.cancel[funName].response = true;
}
},
}
const actions = {
setCancel({ commit }, fn){
commit('SET_CANCEL', fn)
},
response({ commit }, res){
commit('RESPONSE', res)
},
cancel({ commit }, res) {
commit('CANCEL', res)
}
}
复制代码
Axios
拦截器中配置 cancel 相关拦截处理
import axios from "axios";
import store from "@/store";
var instance = axios.create({
timeout: 30000,
withCredentials: true
});
const CancelToken = axios.CancelToken;
// 请求拦截
instance.interceptors.request.use(
req => {
req.cancelToken = new CancelToken(cancel => {
let url = req.url
let str = url.split('/')
str = Array.from(new Set(str))
let index = str.length - 1
let funName = str[index]
store.dispatch("setCancel", { cancel, funName: funName })
});
return req;
},
err => Promise.reject(err)
);
// 响应拦截
instance.interceptors.response.use(
function (response) {
store.dispatch("response", response.config.funName);
if (response.status === 200 && response.data.request_id) {
if (response.data.code == 0) {
return response.data;
} else {
let msg = response.data.msg
Message.error({
message: msg,
duration: 3000,
center: true,
offset: 50,
showClose: true
});
return Promise.reject(error);
}
}
return response;
},
复制代码
调用
以上配置好后,就可以在需要的业务方法中调用
funNames 设置需要取消的请求API名,就可以同时取消一个或多个发送中的请求
handleCancel() {
this.$store.dispatch("cancel", { funNames: ["flavors","transerver_info"] })
}
复制代码
快试试吧~
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END