問題的來源
用el-autocomplete遠程獲取數據時,點擊輸入框會觸發第一次請求,然后輸入搜索文字后會觸發第二次請求,兩次請求間隔較短,有時候會出現第二次請求比第一次請求先返回的情況,導致我們期望的第二次發送的請求返回的數據會被第一次請求返回的數據覆蓋掉
解決思路
在發送第二次請求的時候如果第一次請求還未返回,則取消第一次請求,以保證后發送的請求返回的數據不會被先發送的請求覆蓋。
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的實例發送請求,其他情況未測試
初始方案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() } /* 頁面中獲取列表的函數 */ getList (query, cb) { // 取消之前的請求 listApi.cancelRequest() // 發送請求 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面板并未發送getVideoList請求,控制臺輸出Request canceled!
原因猜想如下:
執行listApi.cancelRequest()時會將listApi.getVideoList({key: 'value'})返回的Promise狀態置為reject,因此在執行listApi.getVideoList({key: 'value'})時并未發送請求,而直接執行catch塊中的代碼,在控制臺輸出Request canceled!。
改進方案B
將getList方案改造如下:
/* 頁面中獲取列表的函數 */ getList (query, cb) { // 發送請求 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) } }) }
此時發送兩個請求時,會在第一個請求返回后取消別一個請求,并在控制臺輸出Request canceled!,但當取消請求觸發后,再次觸發getList方法時結果同方案A。
原因猜想如下:
用方法一觸發取消請求后,此后觸發該請求均返回同一個已經被reject的Promise,因此此例中請求取消后再次執行getList方法時并未發送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 () { // 第一次執行videoService.cancelRequest()時還未發送getVideoList請求,會報錯,添加如下判斷 if (typeof cancel === 'function') { // 取消請求 cancel() } } /* 頁面中獲取列表的函數 */ getList (query, cb) { // 取消之前的請求 listApi.cancelRequest() // 發送請求 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) } }) }
此時重復發送多次`getVideoList請求時,會取消之前發送的請求保證返回數據為最后一次請求返回的數據。
以上這篇axios取消請求的實踐記錄分享就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com