原生ajax中取消请求的方法
const xhr = new XMLHttpReques()
xhr.open('GET', '/api')
xhr.onreadstatechange(() => {
if(xhr.readState === '4' && /^2\d{2}/.test(xhr.status)) {
// sucess
}
})
xhr.send()
// 取消请求
xhr.abort()
axios中取消同一时间的多次请求
最常见的案例就是当我们点击按钮需要去请求数据,如果按钮没有坐任何限制的话,当快速多次点击按钮,可能会同时发出好几条相同的请求,造成服务器压力,也有可能造成页面数据不对,此时我们一般常用的方法就是在axios的全局拦截中做一些限制和判断来规避这种操作
import axios from 'axios'
// 将正在请求的地址存储起来
const pending = []
const CancelToken = axios.CancelToken
/**
* config 请求的axios的配置信息
* c框架中用于取消的回调,在这也会用来判断当前是请求阶段还是返回阶段
*/
const removePending = (config, c) => {
const url = config.url
const index = pending.findIndex(i => i === `${url}&${config.method}`)
// 判断要请求的的地址有没有在pending中
if (index > -1) {
c ? c('数据请求中……') : pending.splice(index, 1)
} else {
c && pending.push(`${url}&${config.method}`)
}
}
// 超时设置
axios.defaults.timeout=5000
axios.interceptors.request.use(function(config) {
// 请求之前判断并添加到pending
config.cancelToken = new CancelToken(c => {
removePending(config, c)
})
return config
},function (error) {
return Promise.reject(error)
})
/*对响应拦截*/
axios.interceptors.response.use(function (response) {
const res=response.data
// 请求回来后删除pending存储
removePending(response.config)
if(response.status !== 200){
return Promise.reject(res)
}else{
return res;
}
}, function (error) {
// 请求回来后删除pending存储
error.config && removePending(error.config)
return Promise.reject(error);
});
axios取消生意tabs中未返回的请求
在一个带有tabs的页面中:
如果我们点击"5万以下",此时出发加载数据,当页面数据未返回的时候,又点击了"5-10万",此时会再次去请求数据,如果"5万以下"的数据返回的比较慢,可能会将"5-10万"返回的数据给顶掉,此时页面显示的数据虽然tags在"5-10万",但是其实显示的是上一个标签的数据;所以我们应该在切换标签的时候,将当前标签未返回的请求取消掉来防止这种混乱的事情发生;在vue模版页面中:
export default {
data() {
return {
list: null,
cancel: null
}
},
create() {
this.getLists()
}
methods: {
// 获取数据
getLists() {
const CancelToken = this.axios.CancelToken
this.axios.get('/api',{
cancelToken: new CancelToken(c => {
// 调用c就可以取消此请求
this.cancel = c
})
}).then(result => {
this.lists = result.data
})
},
// 每次切换标签时先调用此函数,就可以取消请求
cancelAxios() {
this.cancel()
},
changeTabs() {
this.cancelAxios()
this.getLists()
}
},
}
axios源码实现
源码路径:axios/lib/cancel/CancelToken.js
var Cancel = require('./Cancel');
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
// 将new Promise里面的reslove付值给外部的resolvePromise,可以方便在外面控制promise内部的状态改变
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
//上例中new CancelToken穿进去的c就是此处的cancel函数,调用c就相当于调用cancel函数
executor(function cancel(message) {
if (token.reason) {
return;
}
token.reason = new Cancel(message);
// 更改promise的状态,状态改变后会执行下面的then方法
resolvePromise(token.reason);
});
}
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
module.exports = CancelToken;
上接resolvePromise
方法
地址: axios/lib/adapters/xhr.js
if (config.cancelToken) {
// 上面执行完取消后resolvePromise,会触发下面的then方法
// 取消请求
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
所学有限,如果有什么地方分析错误,可以评论出来
原文地址
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。