原生ajax取消请求的方法constxhr=newXMLHttpReques()xhr.open('GET','/api')xhr.onreadstatechange(()=>{if(xhr.readState==='4'&&/^2\d{2}/.test(xhr.status)){//成功}})xhr.send()//取消请求axios中同时取消多个请求最常见的情况是当我们点击按钮请求数据,如果按钮没有任何限制,当按钮被快速点击多次时,可能会同时发送多个相同的请求,造成服务器压力,也可能导致页面数据不正确。这时候,我们一般使用最好的方式是在axios的全局拦截中做一些限制和判断,避免这个操作importaxiosfrom'axios'//存储被请求的地址CancelToken/***config请求的axios的配置信息*c框架中用于取消的回调,也会用来判断当前阶段是请求阶段还是返回阶段*/constremovePending=(config,c)=>{consturl=config.urlconstindex=pending.findIndex(i=>i===`${url}&${config.method}`)//判断请求的地址是否为待定if(index>-1){c?c('Datarequest...'):pending.splice(index,1)}else{c&&pending.push(`${url}&${config.method}`)}}//超时设置axios.defaults.timeout=5000axios.interceptors.request.use(function(config){//请求前判断,添加到pendingconfig.cancelToken=new即可celToken(c=>{removePending(config,c)})returnconfig},function(error){returnPromise.reject(error)})/*拦截响应*/axios.interceptors.response.use(function(response){constres=response.data//请求返回后删除pending存储removePending(response.config)if(response.status!==200){returnPromise.reject(res)}else{returnres;}},function(error){//请求返回error.config&&removePending(error.config)returnPromise.reject(error);})后删除pendingstorageaxios在有tabs的页面取消业务tabs中未返回的请求:如果我们点击“50000以下”,此时开始加载数据,当页面数据未返回时,点击“50000-100000”,然后请求再次获取数据,如果“50000以下”的数据返回比较慢,“50000-100000”返回的数据可能会被丢弃。页面显示的数据虽然是tag中的“50000-100000”,但实际上显示的是前一个tag的数据;所以我们在切换标签页时,取消当前标签页不返回的请求,防止这种混乱的发生;在vue模板页面中:exportdefault{data(){return{list:null,cancel:null}},create(){this.getLists()}methods:{//获取数据getLists(){constCancelToken=this.axios.CancelTokenthis.axios.get('/api',{cancelToken:newCancelToken(c=>{//调用c取消本次请求this.cancel=c})}).then(result=>{this.lists=result.data})},//每次切换调用tab键时优先调用此函数,可以取消请求cancelAxios(){this.cancel()},changeTabs(){this.cancelAxios()this.getLists()}},}axios源码实现源码路径:axios/lib/cancel/CancelToken.jsvarCancel=require('./Cancel');functionCancelToken(executor){if(typeofexecutor!=='function'){thrownewTypeError('executor必须是一个函数。');}//将newPromise中的reslove支付给外部的resolvePromise,可以方便的控制promise内部的状态变化varresolvePromise;this.promise=newPromise(functionpromiseExecutor(resolve){resolvePromise=resolve;});var令牌=这个;//上例中newCancelToken中的c就是这里的cancel函数,调用c相当于调用了cancel函数executor(functioncancel(message){if(token.reason){return;}token.reason=newCancel(message);//改变promise的状态,状态改变后,会执行下面的then方法resolvePromise(token.reason);});}CancelToken.prototype.throwIfRequested=functionthrowIfRequested(){if(this.reason){throwthis.reason;}};CancelToken.source=functionsource(){varcancel;vartoken=newCancelToken(functionexecutor(c){cancel=c;});返回{令牌:令牌,取消:取消};};module.exports=CancelToken;linkresolvePromise方法地址:axios/lib/adapters/xhr.jsif(config.cancelToken){//resolvePromise上面执行完取消后,会触发下面的then方法//取消请求config.cancelToken.promise.then(functiononCanceled(cancel){if(!request){return;}request.abort();reject(cancel);//清理请求request=null;});}学习有限,如有分析错误,可以评论原文地址
