axios delete有请求体吗_封装 axios 取消重复请求
編者按:本文作者舒麗琦,奇舞團前端開發工程師
在我們web開發過程中,很多地方需要我們取消重復的請求。但是哪種場合需要我們取消呢?我們如何取消呢?帶著這些問題我們閱讀本文。
閱讀完本文,你將了解以下內容:
需要取消重復請求的場景
我們如何取消重復請求
axios如何取消重復的請求
封裝axios
如何給開源的項目提供源碼
如何在本地調試npm包
提出問題
最近做的項目中,用的用戶經常遇到這樣的問題:
用戶頻繁切換篩選條件去請求數據,初次的篩選條件數據量大。用的時間比較多。后面的篩選條件的數據量小。導致后面請求的數據先返回。內容先顯示在頁面上。但是等一段時間,初次(或者前面)的請求數據返回了, 會覆蓋后面的請求的數據。這就導致了篩選條件和內容不一致的情況。
用戶點擊了一次提交按鈕,接口沒有很快響應,導致頁面沒辦法做邏輯語句判斷的提示。用戶覺得可能沒提交上,便會快速又點了按鈕幾次。如果后端沒有去重的判斷,就會導致數據中有很多條重復的數據。
這些問題給用戶的體驗是很不友好的。那么取消無用的請求是很有必要的。
解決思路
我們用的請求庫是axios。那么我們可以在請求的時候攔截請求判斷當前的請求是否重復,如果重復我們就取消當前的請求。大致的實現過程如下:
我們把目前處于pending的請求存儲(假如我們放在一個數組)起來。每個請求發送之前我們都要判斷當前這個請求是否已經存在于這個數組。如果存在,說明請求重復了,我們就在數組中找到重復的請求并且取消。如果不存在,說明這個請求不是重復的,正常發送并且把這個請求api添加在數據中,等請求結束之后刪除數組中的這個api。
我們這個解決思路有了,但是axios如何取消請求的呢?我們先來了解下
axios 如何取消請求
查看axios文檔發現axios提供了兩種取消請求的方法(http://www.axios-js.com/zh-cn/docs/#%E5%8F%96%E6%B6%88)
第一種方法
通過axios.CancelToken.source生成取消令牌token和取消方法cancel
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?{
????// 處理錯誤
??}
});
axios.post('/user/12345',?{
??name:?'new name'
},?{
??cancelToken:?source.token
})
// 取消請求 (消息參數是可選的)
source.cancel('Operation canceled by the user.');
第二種方式
通過傳遞一個 executor 函數到 CancelToken 的構造函數來創建 cancel token
const?CancelToken?=?axios.CancelToken;
let?cancel;
axios.get('/user/12345',?{
??cancelToken:?new?CancelToken(function?executor(c)?{
????// executor 函數接收一個 cancel 函數作為參數
????cancel?=?c;
??})
});
// 取消請求
cancel();
封裝axios
解決取消請求的思路有了,取消請求的辦法也有了,那么剩下的就是封裝了
由于同事之前已經封裝了axios——very-axios(https://github.com/verymuch/very-axios) (基于 axios 進行二次封裝,更簡單、更統一地使用 axios)。那么我們就這個基礎上提一個pr吧。那么從現在開始我們就一步一步的來實現,這個過程包含了【如何給開源的項目貢獻代碼】【如何在本地調試npm】如果已經了解的同學可以直接略過。
準備工作
由于同事已經封裝了axios并且已經開源了。那么我貢獻代碼的方式主要有兩種:
代碼倉庫的管理者給我們添加這個倉庫的寫入權限,如果這樣,我們就可以直接提push。
如果我們沒有權限(大多數情況)。我們使用經典的fork & pull request 的方式來提交代碼。
我們采用的第二種方式。我們去 very-axios(https://github.com/verymuch/very-axios) 把代碼fork到自己的倉庫(如果你還沒有自己的github,需要自己注冊下哦)。
那么你回到自己的github倉庫下面就會看有一個一摸一樣的項目
那么我們現在就可以git clone這個倉庫的代碼到本地,新建branch進行開發,就比如我新建了一個這樣的branch:
現在已經有本地的代碼了,但是我們如何本地化調試npm包呢?那就需要npm link 了
首先在我們要修改的npm 包中npm link:
之后我們會得到
/Users/shuliqi/.nvm/versions/node/v12.17.0/lib/node_modules/very-axios?->?/Users/shuliqi/study/axios/very-axios
這意思就是我們把very-axios鏈接到全局的node_modules
然后我們進入我們my-project-of-axios 目錄下面執行npm link very-axios 如圖:
這意思就是very-axios被安裝在my-project-of-axios 下面了。very-axios的修改都會同步到my-project-of-axios。就實現本地測試了。
我們在my-project-of-axios中的HelloWorld.vue文件中做列子。
如果這里看的不是很懂的同學可以看看這兩篇文章:如何在本地調試npm包(https://github.com/allenGKC/Blog/issues/13)。如何使用 GitHub Flow 給開源項目貢獻代碼(https://juejin.im/post/6844903636863041550)
開始封裝
準備工作完成了, 那我們開始封裝的事情。根據我們之前的思路。我們采用axios 如何取消請求的第一種方式。
聲明一個Map。用來存儲每個請求的 標識 和 取消的函數
// 存儲每個請求的標識和取消的函數
this.pendingAjax?=?new?Map();
自定一個字段來讓用戶自己決定是否需要取消重復的請求
// 是否取消重復的請求
cancelDuplicated?=?false,
自定一個字段來讓用戶是否有全局的統一的設置重復標識的函數。如果沒有設置全局的統一的函數,則默認是請求的method 和url作為重復的標識
// 生成重復標識的方式
duplicatedKeyFn,
this.duplicatedKeyFn?=?isFunction(duplicatedKeyFn)???duplicatedKeyFn?:?(config)?=>?`${config.method}${config.url}`;
添加請求
/**
?* 將請求添加到pendingAjax
?* @param {Object} config
?*/
addPendingAjax(config)?{
??//?是否需要取消重復的請求
??if?(!this.cancelDuplicated)?return
??const?veryConfig?=?config.veryConfig?||?{};
??const?duplicatedKey?=?JSON.stringify({
????duplicatedKey:?veryConfig.duplicatedKey?||?this.duplicatedKeyFn(config),
????type:?REQUEST_TYPE.DUPLICATED_REQUEST,
??});
??config.cancelToken?=?config.cancelToken?||?new?axios.CancelToken((cancel)?=>?{
????// 如果pendingAjax中不存在當前請求,添加進去
????if?(duplicatedKey?&&?!this.pendingAjax.has(duplicatedKey))?{
??????this.pendingAjax.set(duplicatedKey,?cancel);
????}
??});
}
這里面我們可以使用duplicatedKey字段來讓用戶對單一請求自定義重復的標識。或者可以使用一個函數duplicatedKeyFn統一的讓用戶自定義重復的標識
刪除請求
/**
???* 從pendingAjax中刪除請求
???* @param {Object} config
???*/
??removePendingAjax(config)?{
????// 是否需要取消重復的請求
????if?(!this.cancelDuplicated)?return
????const?veryConfig?=?config.veryConfig?||?{};
????const?duplicatedKey?=?JSON.stringify({
??????duplicatedKey:?veryConfig.duplicatedKey?||?this.duplicatedKeyFn(config),
??????type:?REQUEST_TYPE.DUPLICATED_REQUEST,
????});
????// 如果pendingAjax中存在當前請求, 取消當前請求并將其刪除
????if?(duplicatedKey?&&?this.pendingAjax.has(duplicatedKey))?{
??????const?cancel?=?this.pendingAjax.get(duplicatedKey);
??????cancel(duplicatedKey);
??????this.pendingAjax.delete(duplicatedKey);
????}
??}
封裝好了, 我們在哪里使用呢?肯定是在請求開始之前和請求完成之后使用。
在請求之前
// 攔截請求
this.axios.interceptors.request.use((config)?=>?{
??//?在請求開始之前檢查先前的請求
??this.removePendingAjax(config);
??// 將當前請求添加到pendingAjax
??this.addPendingAjax(config);
??// ...
});
在請求完成之后去掉該請求
// 攔截響應
this.axios.interceptors.response.use(response?=>?{
??removePending(response)
??return?response
},?error?=>?{
??// ...
})
到現在已經完成了該有的功能, 但是取消請求的錯誤我們不該返回給用戶。所以:
(err)?=>?{
//?類型是否為重復請求
let?isDuplicatedType;
try?{
??const?errorType?=?(JSON.parse(error.message)?||?{}).type
??isDuplicatedType?=?errorType?===?REQUEST_TYPE.DUPLICATED_REQUEST;
}?catch?(error)?{
??isDuplicatedType?=?false
}
if?(isDuplicatedType)?return;
}
我們在請求完成之后的err里面做一個判斷,判斷如果當前請求是取消的類型,我們就不返回給用戶錯誤的提示信息。
總結
至此,完成了我們的封裝。完成的pr地址:(https://github.com/verymuch/very-axios/pull/1)。本文測試npm包的項目地址:(https://github.com/shuliqi/my-project-of-axios)
關于奇舞周刊
《奇舞周刊》是360公司專業前端團隊「奇舞團」運營的前端技術社區。關注公眾號后,直接發送鏈接到后臺即可給我們投稿。
總結
以上是生活随笔為你收集整理的axios delete有请求体吗_封装 axios 取消重复请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的世界小七解说大全(我的世界小七等价交
- 下一篇: 你的Windows许可证即将过期win1