一篇文章讓你看懂封裝Axios
前言
看很多網(wǎng)上的人的封裝 Axios 教程,但或多或少都有不太合適的點(diǎn),這里為大家推薦我的最佳實(shí)踐。
攔截器不要返回?cái)?shù)據(jù),依然返回 AxiosResponse 對(duì)象
網(wǎng)上的文章都讓你用 攔截器 直接返回?cái)?shù)據(jù),這種作法其實(shí)是非常不妥的,這樣會(huì)讓你后續(xù)的功能很難進(jìn)行拓展。
不推薦的做法
import Axios from 'axios' const client = Axios.create({ // 你的配置 }) client.interceptors.response.use(response => { // 網(wǎng)上的做法都是讓你直接返回?cái)?shù)據(jù) // 這導(dǎo)致后續(xù)的一些功能難以支持 return response.data }) export default client
推薦的做法
推薦使用函數(shù)代替攔截器
import Axios, { AxiosRequestConfig } from 'axios' const client = Axios.create({ // 你的配置 }) export async function request(url: string, config?: AxiosRequestConfig) { const response = await client.request({ url, ...config }) const result = response.data // 你的業(yè)務(wù)判斷邏輯 return result } export default client
到這里可能有人會(huì)說(shuō)太麻煩,請(qǐng)稍等,繼續(xù)往下看。
為你的請(qǐng)求添加拓展
很多時(shí)候,我們的開(kāi)發(fā)流程是這樣的:
發(fā)送請(qǐng)求 => 拿到數(shù)據(jù) => 渲染內(nèi)容
但可惜的是,這只是理想情況,在某些特殊情況下,你還是需要處理異?;蝾~外的支持,如:
- 當(dāng)請(qǐng)求失敗,希望能夠自動(dòng)重試3次以上再失敗
- 分頁(yè)數(shù)據(jù)中,當(dāng)新的請(qǐng)求發(fā)出,自動(dòng)中斷上一次的請(qǐng)求
- 第三方提供 jsonp 接口,而你又只能使用靜態(tài)頁(yè)時(shí) (ps: Axios 不支持 jsonp)
- 更多
當(dāng)發(fā)送以上場(chǎng)景時(shí),你只能默默的寫(xiě)代碼支持,但如果你不攔截 Axios 的響應(yīng),那就可以使用開(kāi)源社區(qū)提供的方案。
支持請(qǐng)求重試
安裝 axios-retry,可以讓你的 Axios 支持自動(dòng)重試的功能
import Axios, { AxiosRequestConfig } from 'axios' import axiosRetry from 'axios-retry' const client = Axios.create({ // 你的配置 }) // 安裝 retry 插件 // 當(dāng)請(qǐng)求失敗后,自動(dòng)重新請(qǐng)求,只有3次失敗后才真正失敗 axiosRetry(client, { retries: 3 }) export async function request(url: string, config?: AxiosRequestConfig) { const response = await client.request({ url, ...config }) const result = response.data // 你的業(yè)務(wù)判斷邏輯 return result } // 只有3次失敗后才真正失敗 const data = request('http://example.com/test')
PS: axios-retry 插件支持配置單個(gè)請(qǐng)求
支持 jsonp 請(qǐng)求
安裝 axios-jsonp,可以讓你的 Axios 支持 jsonp 的功能。
import Axios, { AxiosRequestConfig } from 'axios' import jsonpAdapter from 'axios-jsonp' const client = Axios.create({ // 你的配置 }) export async function request(url: string, config?: AxiosRequestConfig) { const response = await client.request({ url, ...config }) const result = response.data // 你的業(yè)務(wù)判斷邏輯 return result } export function jsonp(url: string, config?: AxiosRequestConfig) { return request(url, { ...config, adapter: jsonpAdapter }) } // 你現(xiàn)在可以發(fā)送 jsonp 的請(qǐng)求了 const data = jsonp('http://example.com/test-jsonp')
支持 URI 版本控制
有開(kāi)發(fā) Web API 經(jīng)驗(yàn)的人都會(huì)遇到一個(gè)問(wèn)題,如果 API 出現(xiàn)重大變更的時(shí)候,如何保證舊版可用的情況下,發(fā)布新的 API?
這種情況在服務(wù)端開(kāi)發(fā)場(chǎng)景中,其實(shí)并不罕見(jiàn),尤其是對(duì)外公開(kāi)的 API,如: 豆瓣 API (已失效)。
當(dāng)前主流的支持 3 種類型的版本控制:
類型 | 描述 |
---|---|
URI Versioning | 版本將在請(qǐng)求的 URI 中傳遞(默認(rèn)) |
Header Versioning | 自定義請(qǐng)求標(biāo)頭將指定版本 |
Media Type Versioning | Accept 請(qǐng)求的標(biāo)頭將指定版本 |
URI 版本控制 是指在請(qǐng)求的 URI 中傳遞的版本,例如 https://example.com/v1/route
和 https://example.com/v2/route
。
import Axios, { AxiosRequestConfig } from 'axios' const client = Axios.create({ // 你的配置 }) client.interceptors.request.use(config => { // 最簡(jiǎn)單的方案 config.url = config.url.replace('{version}', 'v1') return config }) // GET /api/v1/users request('/api/{version}/users')
Header 和 Media Type 模式,可以參考如下文章來(lái)實(shí)現(xiàn)
保持請(qǐng)求唯一
在一個(gè)支持翻頁(yè)的后臺(tái)表格頁(yè),一個(gè)用戶擊翻頁(yè)按鈕,請(qǐng)求發(fā)出等待響應(yīng),但用戶這時(shí)點(diǎn)擊搜索,需要重新獲取數(shù)據(jù),支持你的情況可能是:
- 翻頁(yè)請(qǐng)求先回,搜索數(shù)據(jù)再回,數(shù)據(jù)顯示正常
- 搜索數(shù)據(jù)先回,翻頁(yè)數(shù)據(jù)再回,數(shù)據(jù)顯示異常(通常在負(fù)載均衡的場(chǎng)景中出現(xiàn))
為此,你希望能夠自動(dòng)取消上一次請(qǐng)求,于是你看了 Axios 的取消請(qǐng)求,但好多地方都需要用到,于是可以將這個(gè)功能封裝成獨(dú)立的函數(shù)。
import Axios from 'axios' const CancelToken = Axios.CancelToken export function withCancelToken(fetcher) { let abort function send(data, config) { cancel() // 主動(dòng)取消 const cancelToken = new CancelToken(cancel => (abort = cancel)) return fetcher(data, { ...config, cancelToken }) } function cancel(message = 'abort') { if (abort) { abort(message) abort = null } } return [send, cancel] }
使用
function getUser(id: string, config?: AxiosRequestConfig) { return request(`api/user/${id}`, config) } // 包裝請(qǐng)求函數(shù) const [fetchUser, abortRequest] = withCancelToken(getUser) // 發(fā)送請(qǐng)求 // 如果上一次請(qǐng)求還沒(méi)回來(lái),會(huì)被自動(dòng)取消 fetchUser('1000') // 通常不需要主動(dòng)調(diào)用 // 但可以在組件銷毀的生命周期中調(diào)用 abortRequest()
這樣不需要自動(dòng)取消的時(shí)候,直接使用原函數(shù)即可,也不會(huì)影響原函數(shù)的使用
后語(yǔ)
Axios 封裝其實(shí)還有很多事情可以做,比如 全局錯(cuò)誤處理 (一樣不能影響正常請(qǐng)求) 等,封裝也不應(yīng)該只是利用攔截器直接返回?cái)?shù)據(jù)。
另外請(qǐng)求模塊應(yīng)該保持獨(dú)立,推薦拓展 AxiosRequestConfig
或做成一個(gè)個(gè)獨(dú)立的函數(shù),提供給外部調(diào)用,方便做成一個(gè)獨(dú)立的 HTTP 模塊。
總結(jié)
到此這篇關(guān)于封裝Axios的文章就介紹到這了,更多相關(guān)封裝Axios內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue報(bào)錯(cuò)"Failed?to?resolve?loader:less-loader"的解決方
這篇文章主要給大家介紹了關(guān)于Vue報(bào)錯(cuò)"Failed?to?resolve?loader:less-loader"的解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)同樣遇到這樣問(wèn)題的朋友具有一定的需要的朋友可以參考下2023-02-02Nuxt封裝@nuxtjs/axios請(qǐng)求后端數(shù)據(jù)方式
這篇文章主要介紹了Nuxt封裝@nuxtjs/axios請(qǐng)求后端數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10vue.js2.0點(diǎn)擊獲取自己的屬性和jquery方法
下面小編就為大家分享一篇vue.js2.0點(diǎn)擊獲取自己的屬性和jquery方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02Vue實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本內(nèi)容的例子
今天小編就為大家分享一篇Vue實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本內(nèi)容的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11vue3+vite中使用import.meta.glob的操作代碼
在vue2的時(shí)候,我們一般引入多個(gè)js或者其他文件,一般使用? require.context 來(lái)引入多個(gè)不同的文件,但是vite中是不支持 require的,他推出了一個(gè)功能用import.meta.glob來(lái)引入多個(gè),單個(gè)的文件,下面通過(guò)本文介紹vue3+vite中使用import.meta.glob,需要的朋友可以參考下2022-11-11element-plus dialog v-loading不生效問(wèn)題及解決
這篇文章主要介紹了element-plus dialog v-loading不生效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03vue 實(shí)現(xiàn)動(dòng)態(tài)路由的方法
這篇文章主要介紹了vue 實(shí)現(xiàn)動(dòng)態(tài)路由的方法,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07