axios取消請求的實踐記錄分享
問題的來源
用el-autocomplete遠(yuǎn)程獲取數(shù)據(jù)時,點擊輸入框會觸發(fā)第一次請求,然后輸入搜索文字后會觸發(fā)第二次請求,兩次請求間隔較短,有時候會出現(xiàn)第二次請求比第一次請求先返回的情況,導(dǎo)致我們期望的第二次發(fā)送的請求返回的數(shù)據(jù)會被第一次請求返回的數(shù)據(jù)覆蓋掉
解決思路
在發(fā)送第二次請求的時候如果第一次請求還未返回,則取消第一次請求,以保證后發(fā)送的請求返回的數(shù)據(jù)不會被先發(fā)送的請求覆蓋。
axios官方文檔取消請求說明
方法一:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
方法二:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
})
});
// cancel the request
cancel();
不可行方案
注:本例采用的的axios的實例發(fā)送請求,其他情況未測試
初始方案A
請求時的代碼如下:
/* 接口listApi.getList方法如下 */
const CancelToken = axios.CancelToken
const source = CancelToken.source()
getVideoList ({
key
}) {
return axiosInstance.post('/video/list', {
key
}, {
cancelToken: source.token
})
},
cancelRequest () {
// 取消請求
source.cancel()
}
/* 頁面中獲取列表的函數(shù) */
getList (query, cb) {
// 取消之前的請求
listApi.cancelRequest()
// 發(fā)送請求
listApi.getVideoList({key: 'value'}).then(resp => {
// handle response data
}).catch(err => {
if (axios.isCancel(err)) {
console.log('Request canceled!')
} else {
this.$message.error(err.message)
}
})
}
此時chrome的Network面板并未發(fā)送getVideoList請求,控制臺輸出Request canceled!
原因猜想如下:
執(zhí)行l(wèi)istApi.cancelRequest()時會將listApi.getVideoList({key: 'value'})返回的Promise狀態(tài)置為reject,因此在執(zhí)行l(wèi)istApi.getVideoList({key: 'value'})時并未發(fā)送請求,而直接執(zhí)行catch塊中的代碼,在控制臺輸出Request canceled!。
改進(jìn)方案B
將getList方案改造如下:
/* 頁面中獲取列表的函數(shù) */
getList (query, cb) {
// 發(fā)送請求
listApi.getVideoList({key: 'value'}).then(resp => {
// handle response data
// 取消請求
listApi.cancelRequest()
}).catch(err => {
if (axios.isCancel(err)) {
console.log('Request canceled!')
} else {
this.$message.error(err.message)
}
})
}
此時發(fā)送兩個請求時,會在第一個請求返回后取消別一個請求,并在控制臺輸出Request canceled!,但當(dāng)取消請求觸發(fā)后,再次觸發(fā)getList方法時結(jié)果同方案A。
原因猜想如下:
用方法一觸發(fā)取消請求后,此后觸發(fā)該請求均返回同一個已經(jīng)被reject的Promise,因此此例中請求取消后再次執(zhí)行g(shù)etList方法時并未發(fā)送getVideoList請求,而是在控制臺直接輸出Request canceled!
可行方案
可行方案C
代碼如下:
/* 接口listApi.getList方法如下 */
const CancelToken = axios.CancelToken
let cancel
getVideoList ({
key
}) {
return axiosInstance.post('/video/list', {
key
}, {
cancelToken: new CancelToken(function executor (c) {
cancel = c
})
})
},
cancelRequest () {
// 第一次執(zhí)行videoService.cancelRequest()時還未發(fā)送getVideoList請求,會報錯,添加如下判斷
if (typeof cancel === 'function') {
// 取消請求
cancel()
}
}
/* 頁面中獲取列表的函數(shù) */
getList (query, cb) {
// 取消之前的請求
listApi.cancelRequest()
// 發(fā)送請求
listApi.getVideoList({key: 'value'}).then(resp => {
// handle response data
}).catch(err => {
if (axios.isCancel(err)) {
console.log('Request canceled!')
} else {
this.$message.error(err.message)
}
})
}
此時重復(fù)發(fā)送多次`getVideoList請求時,會取消之前發(fā)送的請求保證返回數(shù)據(jù)為最后一次請求返回的數(shù)據(jù)。
以上這篇axios取消請求的實踐記錄分享就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue3前端做打印頁面信息實現(xiàn)打印功能(打印界面某個部分)
這篇文章主要介紹了如何使用vue3-print-nb依賴在Vue?3項目中實現(xiàn)頁面打印功能,提供了完整的代碼示例,大家可以根據(jù)項目需求選擇合適的打印方法,需要的朋友可以參考下2025-02-02
vue+elementui實現(xiàn)動態(tài)控制表格列的顯示和隱藏
這篇文章主要介紹了vue+elementui實現(xiàn)動態(tài)控制表格列的顯示和隱藏,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04
vue使用高德地圖根據(jù)坐標(biāo)定位點的實現(xiàn)代碼
這篇文章主要介紹了vue使用高德地圖根據(jù)坐標(biāo)定位點的實現(xiàn)代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08
VUE Error: getaddrinfo ENOTFOUND localhost
這篇文章主要介紹了VUE Error: getaddrinfo ENOTFOUND localhost,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05

