axios取消請求
這里就是分析一下接口請求需要被取消時的一些操作
因為我是用vue寫的項目,所以標配用的是axios,怎么在axios中取消已經發送的請求呢?
1.在這之前我們還是先介紹一下原生js的abort()這個方法。
直接上代碼會比較好一點
<divclass="page"id="app"><buttonclass="get-msg">獲取數據</button><buttonclass="cancel">取消獲取</button></div><script>
var currentAjax = null
$('.get-msg').click(function () {
currentAjax = $.ajax({
type: 'GET',
url: 'http://jsonplaceholder.typicode.com/comments',
success: function (res) {
console.log(res)
},
error: function (err) {
console.log("獲取失敗")
}
})
})
$('.cancel').click(function () {
if (currentAjax) {
currentAjax.abort()
}
})
</script>
點擊獲取數據按鈕打印出來的數據
點擊獲取數據之后超超超快快快的手速點擊取消獲取按鈕打印出來的效果
看這兩張效果圖就知道,我們的abort()方法起作用了!!!!
2.在axios中取消接口請求操作
好了,接下來才是我們的主題,Axios官方提供了一個取消接口請求的方法,但是怎么用這個方法官網寫的很簡略(不知道是不是我沒找全的問題),反正官網的axios取消接口請求累的半死沒看懂,后來是扒了很多大佬的博客,才自己理解出來的
Axios 提供了一個 CancelToken的函數,這是一個構造函數,該函數的作用就是用來取消接口請求的,至於怎么用,看代碼吧,我在代碼中寫了注解
<body><divclass="page"id="app"><button@click="getMsg"class="get-msg">獲取數據</button><button@click="cancelGetMsg"class="cancel">取消獲取</button><ul><liv-for="item in items">{{item.name}}</li></ul></div><script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
items: [],
cancel: null
},
methods: {
getMsg () {
let CancelToken = axios.CancelToken
let self = this
axios.get('http://jsonplaceholder.typicode.com/comments', {
cancelToken: new CancelToken(function executor(c) {
self.cancel = c
console.log(c)
// 這個參數 c 就是CancelToken構造函數里面自帶的取消請求的函數,這里把該函數當參數用
})
}).then(res => {
this.items = res.data
}).catch(err => {
console.log(err)
})
//手速夠快就不用寫這個定時器了,點擊取消獲取就可以看到效果了
setTimeout(function () {
//只要我們去調用了這個cancel()方法,沒有完成請求的接口便會停止請求
self.cancel()
}, 100)
},
//cancelGetMsg 方法跟上面的setTimeout函數是一樣的效果,因為手速不夠快,哦不,是因為網速太快,導致我來不及點取消獲取按鈕,數據就獲取成功了
cancelGetMsg () {
// 在這里去判斷你的id 1 2 3,你默認是展示的tab1,點擊的時候不管你上一個請求有沒有執行完都去調用這個cancel(),
this.cancel()
}
}
})
</script></body>
上兩張效果圖展示一下:
點擊獲取數據按鈕獲獲取到了數據
點擊獲取數據之后,用快快快的佛山無影手點擊了取消獲取得到的效果
這樣,就完美的解決了我遇到的問題了,點擊tab切換的時候,網絡敢延遲,我就敢掐掉你的請求,保證我下一個請求不被影響
3.重復點擊問題
那我們經常開發的時候會遇到一個重復點擊的問題,短時間內多次點擊同一個按鈕發送請求會加重服務器的負擔,消耗瀏覽器的性能,多以絕大多數的時候我們需要做一個取消重復點擊的操作
在vue開發中,這個方法一樣完美解決這一問題,通常我們會封裝一遍axios,這里我們便可以將此功能封裝到攔截器里面去
import axios from 'axios';
axios.defaults.timeout = 5000;
axios.defaults.baseURL ='';
let pending = []; //聲明一個數組用於存儲每個ajax請求的取消函數和ajax標識
let cancelToken = axios.CancelToken;
let removePending = (ever) => {
for(let p in pending){
if(pending[p].u === ever.url + '&' + ever.method) { //當當前請求在數組中存在時執行函數體
pending[p].f(); //執行取消操作
pending.splice(p, 1); //把這條記錄從數組中移除
}
}
}
//http request 攔截器
axios.interceptors.request.use(
config => {
config.data = JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/x-www-form-urlencoded'
}
// ------------------------------------------------------------------------------------
removePending(config); //在一個ajax發送前執行一下取消操作
config.cancelToken = new cancelToken((c)=>{
// 這里的ajax標識我是用請求地址&請求方式拼接的字符串,當然你可以選擇其他的一些方式
pending.push({ u: config.url + '&' + config.method, f: c });
});
// -----------------------------------------------------------------------------------------
return config;
},
error => {
return Promise.reject(err);
}
);
//http response 攔截器
axios.interceptors.response.use(
response => {
// ------------------------------------------------------------------------------------------
removePending(res.config); //在一個ajax響應后再執行一下取消操作,把已經完成的請求從pending中移除
// -------------------------------------------------------------------------------------------
if(response.data.errCode ==2){
router.push({
path:"/login",
querry:{redirect:router.currentRoute.fullPath}//從哪個頁面跳轉
})
}
return response;
},
error => {
return Promise.reject(error)
}
)
這是我自己項目用來封裝axios的代碼,里面加入了取消重復點擊事件的方法.