文章目錄
Axios學習(5)—axios請求的封裝與使用
思路分析
axios 請求的封裝,無非是爲了方便代碼管理,我們可以使用抽離拆分的思想,將不同功能模塊的接口處理成不同的模塊,然後封裝一個方法,專門用於數據交互。
第一步:新建 src/service/contactApi.js 文件
const CONTACT_API = {
// 獲取聯繫人列表
getContactList:{
method:'get',
url:'/contactList'
},
// 新建聯繫人 form-data
newContactForm:{
method:'post',
url:'/contact/new/form'
},
// 新建聯繫人 application/json
newContactJson:{
method:'post',
url:'/contact/new/json'
},
// 編輯聯繫人
editContact:{
method:'put',
url:'/contact/edit'
},
// 刪除聯繫人
delContact:{
method:'delete',
url:'/contact'
}
}
export default CONTACT_API
備註:該文件的用途只有一個,定義不同的接口請求信息(包含 method、***url***等)並導出使用。當接口增加或者刪除的時候,只需要定義在該文件中即可。
第二步:新建 src/service/http.js 文件
import axios from 'axios'
import service from './contactApi'
import { Toast } from 'vant'
// service 循環遍歷輸出不同的請求方法
let instance = axios.create({
baseURL: 'http://localhost:9000/api',
timeout: 1000
})
const Http = {}; // 包裹請求方法的容器
// 請求格式/參數的統一
for (let key in service) {
let api = service[key]; // url method
// async 作用:避免進入回調地獄
Http[key] = async function(
params, // 請求參數 get:url,put,post,patch(data),delete:url
isFormData = false, // 標識是否是form-data請求
config = {} // 配置參數
) {
let newParams = {}
// content-type是否是form-data的判斷
if (params && isFormData) {
newParams = new FormData()
for (let i in params) {
newParams.append(i, params[i])
}
} else {
newParams = params
}
// 不同請求的判斷
let response = {}; // 請求的返回值
if (api.method === 'put' || api.method === 'post' || api.method === 'patch') {
try {
response = await instance[api.method](api.url, newParams, config)
} catch (err) {
response = err
}
} else if (api.method === 'delete' || api.method === 'get') {
config.params = newParams
try {
response = await instance[api.method](api.url, config)
} catch (err) {
response = err
}
}
return response; // 返回響應值
}
}
// 攔截器的添加
// 請求攔截器
instance.interceptors.request.use(config => {
// 發起請求前做些什麼
Toast.loading({
mask: false,
duration: 0, // 一直存在
forbidClick: true, // 禁止點擊
message: '加載中...'
})
return config
}, () => {
// 請求錯誤
Toast.clear()
Toast('請求錯誤,請求稍後重試')
})
// 響應攔截器
instance.interceptors.response.use(res => {
// 請求成功
Toast.clear()
return res.data
}, () => {
Toast.clear()
Toast('請求錯誤,請求稍後重試')
})
export default Http
具體的思路步驟如下:
-
首先,我們引入contactApi.js文件,別名定義爲 service。
import service from './contactApi'
-
定義新的 axios 實例,針對當前功能模塊聯繫人列表管理 contactList ,配置baseURL基礎域名、timeout請求超時時間等等,區別於其他功能模塊。
let instance = axios.create({ baseURL: 'http://localhost:9000/api', timeout: 1000 })
-
定義 http 作爲請求方法的容器,配置對應的參數(即請求方法中的其他信息,比如 headers,content-type,token等等)。需要注意的是,在其中我們要區分 content-type的形式有兩種:form-data 與 application/json,它們的參數配置不同,form-data 形式的參數,我們需要定義 Formdata 對象。具體如下:
let newParams = {} // content-type是否是form-data的判斷 if (params && isFormData) { newParams = new FormData() for (let i in params) { newParams.append(i, params[i]) } } else { newParams = params }
溫馨提示:其中 isFormData 定義爲 Boolean 變量,用於標識是否爲 FormData 形式。
-
根據不同的請求方式,發起網絡請求,並導出返回值。
// 不同請求的判斷 let response = {}; // 請求的返回值 if (api.method === 'put' || api.method === 'post' || api.method === 'patch') { try { response = await instance[api.method](api.url, newParams, config) } catch (err) { response = err } } else if (api.method === 'delete' || api.method === 'get') { config.params = newParams try { response = await instance[api.method](api.url, config) } catch (err) { response = err } } return response; // 返回響應值
注意:對於不同方法的區別在於:get 與 delete 的參數在 config 中配置,而不是使用 params 。
-
設置請求攔截器與響應攔截器
// 攔截器的添加 // 請求攔截器 instance.interceptors.request.use(config => { // 發起請求前做些什麼 Toast.loading({ mask: false, duration: 0, // 一直存在 forbidClick: true, // 禁止點擊 message: '加載中...' }) return config }, () => { // 請求錯誤 Toast.clear() Toast('請求錯誤,請求稍後重試') }) // 響應攔截器 instance.interceptors.response.use(res => { // 請求成功 Toast.clear() return res.data }, () => { Toast.clear() Toast('請求錯誤,請求稍後重試') })
-
導出src/service/http.js文件,用於其他地方的引入。
export default Http
第三步:在入口文件中導入 http.js ,並掛載到 vue 原型上。
import Http from './service/http'
// 把Http掛載到Vue實例上
Vue.prototype.$Http = Http
第四步:在組件中使用封裝的請求
// 獲取聯繫人列表
async getList(){
let res = await this.$Http.getContactList()
this.list = res.data
},
注意:在使用的時候,我們需要結合 async 與 await 才能正確使用。具體的使用方法是:
- 在定義的網絡請求函數前增加 async 標識。
- 在接收請求返回數據的時候,增加 await 標識。
- 提示:在上面函數中,只有在 res 拿到後纔會執行 this.list = res.data; 相當於在對應的 then 中執行的語句,避免了回調地獄。
總結:
在進行項目開發的時候,我們需要對網絡請求的方法進行封裝,可以有效地減少後期代碼維護的難度,建議開發者根據不同的功能模塊進行拆分,方便後期代碼問題的定位。另外,也能實現代碼的低耦合,避免出現更多的重複代碼。