前言需要取消重复请求的场景:比如输入框搜索需要取消上次重复请求时,tab切换频繁获取数据列表界面,重复界面请求是用户频繁切换操作时,我们调用相同的接口,我们需要先取消上次的接口请求,只请求用户上次操作的接口,否则相同的接口重复请求,接口是异步的,然后很容易获取到不是的数据上次操作需要的数据。axios自己封装了取消事件axios中文文档取消事件axios取消事件代码如下方法一,可以使用CancelToken.source工厂方法创建一个取消令牌,像这样:constCancelToken=axios.CancelToken;constsource=CancelToken.source();axios.get('/user/12345',{cancelToken:source.token}).catch(function(thrown){if(axios.isCancel(thrown)){console.log('请求取消',thrown.message);}else{//处理错误}});axios.post('/user/12345',{name:'newname'},{cancelToken:source.token})//取消请求(消息参数可选)source.cancel('操作被用户取消。');方法2.您还可以通过将执行器函数传递给CancelToken构造函数来创建取消标记:constCancelToken=axios.CancelToken;letcancel;axios.get('/user/12345',{cancelToken:newCancelToken(functionexecutor(c){//执行函数接收一个取消函数作为参数cancel=c;})});//取消requestcancel();单独使用axios时,这两个方法可以是的,但是在vue中封装全局调用axios方法时,第一个方法有问题。axios的cancel方法会取消即将到来的请求,所以使用第二种方法完成axios打包代码如下:importaxiosfrom'axios'importUserModelfrom'../models/user'//interfaceprefixconstPREFIX={mock:'https://yapi.comliq.net/mock/31/',//yapimock地址开发:'http://xxx/',//qa环境制作:'http://xxx/',//生产环境}constenv=process.env.NODE_ENVletinterfacePrefix=PREFIX[env]||PREFIX.production//接口前缀/***config自定义配置项*@paramwithoutCheck不使用默认接口状态校验,直接返回response*@paramreturnOrigin是否返回整个response对象,如果为false,只返回response.data*@parammock是否使用mock服务*@paramtimeout接口请求超时,默认10秒*@paramisCancelRequest可以取消请求*/constconfigDefault={returnOrigin:false,withoutCheck:false,mock:false,timeout:10000}//创建请求者constservice=axios.create(Object.assign({baseURL:'',responseType:'json',headers:{'Content-Type':'application/json;charset=utf-8',},},configDefault))//添加请求拦截器service.interceptors.request.use(request=>{constreqData=request.data||request.paramsif(reqData&&!request.canEmpty){//处理请求参数,清空参数request.data=deleteEmpty(reqData)}//检测接口,自动根据环境切换前缀if(request.url.indexOf('http')===-1){if(request.url[0]==='/'){request.url=request.url.substr(1)}request.url=`${env!=='production'&&request.mock?PREFIX.mock:interfacePrefix}${request.url}`}//如果有鉴权token,需要在请求头中自动添加token,这个token本身封装了获取到的request.headers.accessToken=UserModel.getToken()returnrequest},error=>{returnPromise.reject(error)},)//object对象存储每次newCancelToken生成的方法letsource={}//路径会在每次之前放在这个数组中request,响应成功后会清空requestpathletrequestList=[]//定义cancel方法functioncancelRequest(path,allCancel){//请求列表中存在该路径,即发起重复请求,取消之前的请求if(path&&requestList.includes(path)&&typeofsource[path]==='function'){source[path]('terminaterequest')}elseif(!path&&allCancel){//如果allCancel为真,则请求列表中的所有请求都将被取消。requestList.forEach(el=>{source[el]('批量终止请求')})}}//添加响应拦截器service.interceptors.response.use(res=>{//获取请求的apiconstpath=JSON.stringify(res.config.url)//请求完成后,将本次请求从请求列表中移除requestList=requestList.filter(item=>!path.includes(item))//HTTP状态码2xx状态条目,data.code为200表示数据正确,没有错误},error=>{//非2xx状态入口returnPromise.reject(error)},)//这里只是封装后演示,可以封装其他请求methodsyourselffunctionrequestFn(method,path,params={},options={}){//取消最后一个请求if(requestList.length){cancelRequest(path)}//将isCancelRequest设置为true,将path推入requestList之前请求if(options.isCancelRequest){requestList.push(path)}if(method==='post'){returnservice.post(path,params,{cancelToken:newaxios.CancelToken(c=>{source[path]=c}),...options})}}exportconstapi={axios:service,//原始axios对象//重新封装get函数,统一用户输入get:(path,data,config)=>service.get(path,{params:data,...config}),delete:(path,data,config)=>service.delete(path,{data,...config}),post:(path,data,config)=>requestFn('post',path,data,config),put:(path,data,config)=>service.put(path,data,config),}exportdefaultapi参考:AxioswithcancellationrequestinvueenclosedinVue
