在項(xiàng)目中封裝axios的實(shí)戰(zhàn)過程
前言
在學(xué)習(xí)和做項(xiàng)目的時(shí)候經(jīng)常會(huì)碰到axios,之前做的項(xiàng)目一般都是配置好axios,所以自己一直有個(gè)大概印象,最近有個(gè)機(jī)會(huì)自己可以手動(dòng)配置axios,順便記錄分享一下~
axios封裝的好處
axios封裝的好處是統(tǒng)一處理,提高效率,便于維護(hù)。
你可以像下面一樣這么使用axios請(qǐng)求接口
axios.get('http://localhost:10086/user?ID=12345') .then(response => { //成功后的操作... }) .catch(error => { //失敗后的操作... });
但是當(dāng)接口請(qǐng)求多起來,需求多起來的時(shí)候,在項(xiàng)目中每個(gè)需要接口請(qǐng)求的地方寫一遍這樣的代碼,這樣就會(huì)產(chǎn)生很多重復(fù)性的代碼,降低我們的開發(fā)效率和提高維護(hù)成本。
封裝思路
我們需要一次性集中配置axios,讓配置適應(yīng)我們項(xiàng)目的大部分場景。我們可以新建一個(gè)js文件,使用自定義配置新建一個(gè) axios 實(shí)例,然后對(duì)實(shí)例進(jìn)行基本配置,在請(qǐng)求前(請(qǐng)求體處理),請(qǐng)求后(返回的結(jié)果處理)等這些階段添加一些我們需要的處理,然后將其導(dǎo)出使用。
配置的優(yōu)先順序
配置會(huì)以一個(gè)優(yōu)先順序進(jìn)行合并。這個(gè)順序是:在 lib/defaults.js 找到的庫的默認(rèn)值,然后是實(shí)例的 defaults 屬性,最后是請(qǐng)求的 config 參數(shù)。(這樣有些特殊的場景我們也可以單獨(dú)處理)
node_modules文件夾下axios庫文件下的lib/defaults.js。
自定義實(shí)例默認(rèn)值
const instance = axios.create({ baseURL: 'https://api.example.com' });
請(qǐng)求的config參數(shù)
axios({ method:'get', url:'http://bit.ly/2mTM3nY', responseType:'stream' }).then(function(response) { response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) });
axios實(shí)例配置
1、定義一些常規(guī)的配置
設(shè)置BaseUrl
baseUrl一般有分為生產(chǎn)、開發(fā)、測(cè)試等多個(gè)地址,我們可以弄一個(gè)config.js進(jìn)行存放,如果是vue或react我們可以新建env等文件進(jìn)行存放,下面的baseUrl是使用react的環(huán)境變量的。
- 設(shè)置timeout請(qǐng)求超時(shí)的時(shí)間
- 設(shè)置數(shù)據(jù)請(qǐng)求的格式Content-Type(有 application/x-www-form-urlencoded、multipart/form-data、application/json...)等等
import axios from 'axios' export const request = createAxiosInstance() function createAxiosInstance () { const instance = axios.create({ baseURL: process.env.REACT_APP_BASE_URL, timeout: 5000, headers: { // 可定義統(tǒng)一的請(qǐng)求頭部 post: { 'Content-Type': 'application/json' } ... } }) return instance }
2、請(qǐng)求前加一些我們需要的操作,
比如需要在請(qǐng)求頭里添加token
請(qǐng)求參數(shù)判空處理
(下圖的例子傳了空的name和personId,這種會(huì)引起歧義,究竟是要獲取參數(shù)值為空還是忽略這些參數(shù)呢,有一些后端會(huì)進(jìn)行一些處理,但前端還是盡量避免~)
每次接口請(qǐng)求時(shí)開啟loading動(dòng)畫效果等等
// 添加請(qǐng)求攔截器(在發(fā)送請(qǐng)求之前做些什么) instance.interceptors.request.use((config) => { //可添加開啟loading效果的函數(shù) loading.open() //token 存在就添加到請(qǐng)求頭里 token && (config.headers.Authorization = token) // 過濾請(qǐng)求參數(shù)中的 null undefined ''的函數(shù) cleanObject() return config })
3、請(qǐng)求返回后,添加攔截操作,
- 處理成功返回的數(shù)據(jù)
比如后端返回的data數(shù)據(jù)可能嵌套了很多層,你可以直接返回你需要的data數(shù)據(jù),這樣業(yè)務(wù)代碼就可以直接拿到最終的數(shù)據(jù),而不用每次去解構(gòu)之類的。
- 統(tǒng)一處理失敗后的異常報(bào)錯(cuò)
接口請(qǐng)求有成功也有失敗,如果你不想在每寫一個(gè)接口請(qǐng)求的時(shí)候都需要去寫一遍失敗的邏輯代碼,并且?guī)缀醵际侵貜?fù)的時(shí)候,那你可以在這里集中進(jìn)行接口的統(tǒng)一的異常處理。如判斷狀態(tài)碼或后端自定義的code,并把后端返回的錯(cuò)誤提示顯示出來。
// 添加響應(yīng)攔截器(對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么) instance.interceptors.response.use((response) => { //可添加關(guān)閉loading效果的函數(shù) loading.close() //解構(gòu)出返回結(jié)果的數(shù)據(jù) const res = response.data //對(duì)自定義code碼進(jìn)行判斷,將成功的數(shù)據(jù)返回出去 const validateStatus = /^(2|3)\d{2}$/ //code為2或3開頭的視作請(qǐng)求成功 if (validateStatus.test(res.code)) { return res //直接return出去我們需要的data } //判斷失敗的code碼并作出提示等操作 if (res.code === 401) { message.error(res.msg) } else { message.warning(res.msg) } return Promise.reject(res) }, (error) => { loading.close() if (error.response.status === 401) { message.error('token失效,請(qǐng)重新登錄!') removeStorageToken() setTimeout(() => { window.location.href = '/login' }, 2000) } else { if (!window.navigator.onLine) { message.warning('網(wǎng)絡(luò)異常,請(qǐng)檢查網(wǎng)絡(luò)是否正常連接') } else if (error.code === 'ECONNABORTED') { message.warning('請(qǐng)求超時(shí)') } else { message.warning('服務(wù)器異常,請(qǐng)聯(lián)系管理員') } } return Promise.reject(error) // 將錯(cuò)誤繼續(xù)返回給到具體頁面 } )
上面有根據(jù)HTTP狀態(tài)碼和自定義code做的一些錯(cuò)誤處理,這里進(jìn)行了錯(cuò)誤攔截后,頁面進(jìn)行業(yè)務(wù)接口調(diào)用的時(shí)候就不用再每次進(jìn)行錯(cuò)誤提示處理。當(dāng)然要根據(jù)不同項(xiàng)目需求進(jìn)行配置。
請(qǐng)求接口方法統(tǒng)一管理
一般我們會(huì)把所有的接口請(qǐng)求方法寫在一起進(jìn)行統(tǒng)一管理,后期更改的時(shí)候也方便查找維護(hù)。
我們可以新建一個(gè)管理api請(qǐng)求的文件夾(如apiList),里面放我們各種請(qǐng)求文件(這里按功能分)。如user.js就存放用戶相關(guān)的請(qǐng)求,其他類推。然后頁面就可以直接引用方法進(jìn)行接口調(diào)用。
import { request } from '../axios' // 獲取用戶信息 export function getUserInfo (userId) { return request.get(`/sys/user/info/${userId}`) }
在組件或頁面直接調(diào)用方法就可以了~
最后放一下完整的示例!大家可以參考一下~
這個(gè)示例配置適用于vue或react,當(dāng)然每個(gè)項(xiàng)目的配置都會(huì)有些不同,小伙伴要根據(jù)自己項(xiàng)目進(jìn)行修改配置和擴(kuò)充~
import axios from 'axios' export const request = createAxiosInstance() function createAxiosInstance () { const instance = axios.create({ baseURL: process.env.REACT_APP_BASE_URL, timeout: 5000, headers: { // 可定義統(tǒng)一的請(qǐng)求頭部 post: { 'Content-Type': 'application/json' } ... } }) // 添加請(qǐng)求攔截器(在發(fā)送請(qǐng)求之前做些什么) instance.interceptors.request.use((config) => { //可添加開啟loading效果的函數(shù) loading.open() //token 存在就添加到請(qǐng)求頭里 token && (config.headers.Authorization = token) // 過濾請(qǐng)求參數(shù)中的 null undefined ''的函數(shù) cleanObject() return config }) // 添加響應(yīng)攔截器(對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么) instance.interceptors.response.use((response) => { //可添加關(guān)閉loading效果的函數(shù) loading.close() //解構(gòu)出返回結(jié)果的數(shù)據(jù) const res = response.data //對(duì)自定義code碼進(jìn)行判斷,將成功的數(shù)據(jù)返回出去 const validateStatus = /^(2|3)\d{2}$/ //code為2或3開頭的視作請(qǐng)求成功 if (validateStatus.test(res.code)) { return res } //判斷失敗的code碼并作出提示等操作 if (res.code === 401) { message.error(res.msg) } else { message.warning(res.msg) } return Promise.reject(res) }, (error) => { loading.close() //可添加關(guān)閉loading效果的函數(shù) if (error.response.status === 401) { message.error('token失效,請(qǐng)重新登錄!') removeStorageToken() setTimeout(() => { window.location.href = '/login' }, 2000) } else { if (!window.navigator.onLine) { message.warning('網(wǎng)絡(luò)異常,請(qǐng)檢查網(wǎng)絡(luò)是否正常連接') } else if (error.code === 'ECONNABORTED') { message.warning('請(qǐng)求超時(shí)') } else { message.warning('服務(wù)器異常,請(qǐng)聯(lián)系管理員') } } return Promise.reject(error) // 將錯(cuò)誤繼續(xù)返回給到具體頁面 } ) return instance }
總結(jié)
到此這篇關(guān)于在項(xiàng)目中封裝axios的文章就介紹到這了,更多相關(guān)項(xiàng)目中封裝axios內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
對(duì)vue下點(diǎn)擊事件傳參和不傳參的區(qū)別詳解
今天小編就為大家分享一篇對(duì)vue下點(diǎn)擊事件傳參和不傳參的區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue.js實(shí)現(xiàn)網(wǎng)格列表布局轉(zhuǎn)換方法
下面小編就為大家?guī)硪黄猇ue.js實(shí)現(xiàn)網(wǎng)格列表布局轉(zhuǎn)換方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08vue3使用axios并封裝axios請(qǐng)求的詳細(xì)步驟
本篇文章分步驟給大家介紹了vue3使用axios并封裝axios請(qǐng)求的詳細(xì)步驟,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友參考下吧2023-06-06Vue通過阿里云oss的url連接直接下載文件并修改文件名的方法
這篇文章主要介紹了Vue通過阿里云oss的url連接直接下載文件并修改文件名的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12vue 綁定對(duì)象,數(shù)組之?dāng)?shù)據(jù)無法動(dòng)態(tài)渲染案例詳解
這篇文章主要介紹了vue 綁定對(duì)象,數(shù)組之?dāng)?shù)據(jù)無法動(dòng)態(tài)渲染案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09vue-cli webpack模板項(xiàng)目搭建及打包時(shí)路徑問題的解決方法
這篇文章主要介紹了vue-cli webpack模板項(xiàng)目搭建以及打包時(shí)路徑問題的解決方法,需要的朋友可以參考下2018-02-02