首次入坑
你是否寫過像我這樣的程式碼?
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
methods:{
getData(){
axios.get('http://api.mozlee.com/getdata').then({data}=>{
//todo bala bala~
})
},
getData2(){
axios.get('http://api.mozlee.com/getdata2').then({data}=>{
//todo bala bala~
})
},
getData3(){
axios.get('http://api.mozlee.com/getdata3').then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
這個時候服務端小夥伴老王來了,告知你api.mozlee.com這個域即將下線,由api.jackma.com替換,並且將http協議全部更新到https協議。你怎麼辦?是不是隻能一個一個去改axios請求的url?而且在修改的過程中十分繁瑣,並且容易出現錯改,漏改。機智的小夥伴已經想到用axios的baseURL去解決這個問題。所以我們改寫一下這個元件。
改造一,使用baseURL
程式碼改寫如下,這樣解決上邊老王提出來的問題。
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import axios from 'axios'
axios.baseURL = 'https://api.jackma.com'
export default {
methods:{
getData(){
axios.get('/getdata').then({data}=>{
//todo bala bala~
})
},
getData2(){
axios.get('/getdata2').then({data}=>{
//todo bala bala~
})
},
getData3(){
axios.get('/getdata3').then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
可是老王這個孩子不省心啊,又過來告訴你我們的/getdata3介面,依然要用老的域名 api.mozlee.com,其他的介面保持 api.jackma.com。此時的你是不是想錘死老王?
改造二,使用create建立例項
面對老王的這次改動,我們來使用axios的create方法建立出不同的用於請求的例項。
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import axios from 'axios'
const mozleeAPI = axios.create({
baseURL:'https://api.mozlee.com',
... // 其他config
})
const jackmaAPI = axios.create({
baseURL:'https://api.jackma.com',
... // 其他config
})
axios.baseURL = 'https://api.jackma.com'
export default {
methods:{
getData(){
jackmaAPI.get('/getdata').then({data}=>{
//todo bala bala~
})
},
getData2(){
jackmaAPI.get('/getdata2').then({data}=>{
//todo bala bala~
})
},
getData3(){
mozleeAPI.get('/getdata3').then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
此時的你總算舒了口氣,完成了這個元件開發,去開發其他元件(功能),但是你發現,TMD這兩個建立的請求例項在別的元件也要用到。
改造三,抽離axios相關例項。
此時的我們應該將請求相關的介面進行抽離,再向外部暴露。這樣在其他元件就可以引入呼叫。 我們新建一個api.js
api.js的內容為
import axios from 'axios'
export const mozleeAPI = axios.create({
baseURL:'https://api.mozlee.com',
... // 其他config
})
export const jackmaAPI = axios.create({
baseURL:'https://api.jackma.com',
... // 其他config
})
複製程式碼
元件A的內容為
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import {mozleeAPI,jackmaAPI} from './api.js'
export default {
methods:{
getData(){
jackmaAPI.get('/getdata').then({data}=>{
//todo bala bala~
})
},
getData2(){
jackmaAPI.get('/getdata2').then({data}=>{
//todo bala bala~
})
},
getData3(){
mozleeAPI.get('/getdata3').then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
元件B的內容為
<template>
<div id="app">
<button @click="getData">載入資料</button>
</div>
</template>
<script>
import {jackmaAPI} from './api.js'
export default {
methods:{
getData(){
jackmaAPI.get('/getdata').then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
到此,可算是解決了多元件複用axios例項的問題了。但是萬惡的老王又TM來了。老王說,hey兄弟,我們的api.jackma.com這個域下的/getdata這個介面需要改一改,老闆覺得/getdata有點醜,我們決定改成/getuser。此時你一邊在心裡問候著老王,一邊竊喜,還好寫的不多,只需要兩個元件的內容。但是仔細一想,善變的老王不一定又會改什麼,要是的API用多了豈不是和最開始使用axios出現了相同問題,容易錯該,漏改。身為一個優秀的程式設計師,必須將其抽象。
改造四,將請求url抽象封裝
api.js的內容為
import axios from 'axios'
const mozleeAPI = axios.create({
baseURL:'https://api.mozlee.com',
... // 其他config
})
const jackmaAPI = axios.create({
baseURL:'https://api.jackma.com',
... // 其他config
})
export getData(){
return jackmaAPI.get('/getuser')
}
export getData2(){
return jackmaAPI.get('/getdata2')
}
export getData3(){
return mozleeAPI.get('/getdata3')
}
複製程式碼
元件A的內容為
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import { getData, getData2, getData3 } from './api.js'
export default {
methods:{
getData(){
getData().then({data}=>{
//todo bala bala~
})
},
getData2(){
getData2().then({data}=>{
//todo bala bala~
})
},
getData3(){
getData3().then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
元件B的內容為
<template>
<div id="app">
<button @click="getData">載入資料</button>
</div>
</template>
<script>
import { getData } from './api.js'
export default {
methods:{
getData(){
getData().then({data}=>{
//todo bala bala~
})
}
}
}
</script>
複製程式碼
如此一來,看你老王還能玩出什麼花活!
老王嘿嘿一笑,兄弟,我們的介面要求在api.mozlee.com域的url上帶上一個時間time的引數,在api.jackma.com域的請求header中新增一個name:lilei的自定義頭。
聰明的你當然不能再介面函式裡邊一個一個加了。
改造五,使用axios request攔截器
api.js的內容為
import axios from 'axios'
const mozleeAPI = axios.create({
baseURL:'https://api.mozlee.com',
... // 其他config
})
mozleeAPI.interceptors.request.use(function (config) {
config.url += `?time=${new Date().getTime()}`
return config
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error)
})
const jackmaAPI = axios.create({
baseURL:'https://api.jackma.com',
... // 其他config
})
jackmaAPI.interceptors.request.use(function (config) {
config.header = Object.assign(config.header ,{'name':'lilei'})
return config
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error)
})
export getData(){
return jackmaAPI.get('/getuser')
}
export getData2(){
return jackmaAPI.get('/getdata2')
}
export getData3(){
return mozleeAPI.get('/getdata3')
}
複製程式碼
這時候的老王確實提不出什麼需求了,但是你發現了一個問題。api.jackma.com域的介面一定返回一種約定好格式的json 如下:
{
data:['lilei','hanmeimei'],
stat:1,
msg:'success'
}
複製程式碼
每次呼叫的時候都需要在Promise的then中做一個判斷,當stat>0是做成功的事,stat!=0的時候做失敗的事。
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import { getData, getData2, getData3 } from './api.js'
export default {
methods:{
getData(){
getData().then({data}=>{
if(data.stat>0){
doSuccess()
}else{
doError()
}
}).catch(err=>{
doError()
})
},
getData2(){
getData2().then({data}=>{
if(data.stat>0){
doSuccess()
}else{
doError()
}
}).catch(err=>{
doError()
})
},
getData3(){
getData3().then({data}=>{
if(data.status){
doSuccess()
}else{
doError()
}
}).catch(err=>{
doError()
})
}
}
}
</script>
複製程式碼
改造六、使用axios response攔截器。
import axios from 'axios'
const mozleeAPI = axios.create({
baseURL:'https://api.mozlee.com',
... // 其他config
})
mozleeAPI.interceptors.request.use(function (config) {
config.url += `?time=${new Date().getTime()}`
return config
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error)
})
const jackmaAPI = axios.create({
baseURL:'https://api.jackma.com',
... // 其他config
})
jackmaAPI.interceptors.request.use(function (config) {
config.header = Object.assign(config.header ,{'name':'lilei'})
return config
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error)
})
// response 攔截器
jackmaAPI.interceptors.response.use(function ({ data }) {
// 對響應資料做點什麼
if (data.stat > 0) {
return data
} else {
return Promise.reject(data)
}
}, function (error) {
console.log(error)
return Promise.reject(error)
})
export getData(){
return jackmaAPI.get('/getuser')
}
export getData2(){
return jackmaAPI.get('/getdata2')
}
export getData3(){
return mozleeAPI.get('/getdata3')
}
複製程式碼
只要是非成功狀態,不管是網路狀態非200,還是200狀態但是response結果的stat為0,我們都把他們reject。
這樣我們在Promise.then中 只做Success相關,catch中只做錯誤相關。改造後的 元件程式碼如下
<template>
<div id="app">
<button @click="getData">載入資料</button>
<button @click="getData2">載入資料2</button>
<button @click="getData3">載入資料3</button>
</div>
</template>
<script>
import { getData, getData2, getData3 } from './api.js'
export default {
methods:{
getData(){
getData().then({data}=>{
doSuccess()
}).catch(err=>{
doError()
})
},
getData2(){
getData2().then({data}=>{
doSuccess()
}).catch(err=>{
doError()
})
},
getData3(){
getData3().then({data}=>{
if(data.status){
doSuccess()
}else{
doError()
}
}).catch(err=>{
doError()
})
}
}
}
</script>
複製程式碼
哈哈,這下基本上可以滿足老王的任性變動,以及自己開發的複用、簡單化開發。
最後的建議
- 一個專案多個域的介面,建議統一管理。建立一個統一的index.js管理不同的域,並且向外暴露axios例項。 index.js
import axios from 'axios'
const mozleeAPI = axios.create({
baseURL:'//api.mozlee.com'
})
const jackmaAPI = axios.create({
baseURL:'//api.jackma.com'
})
const hanmeimeiAPI = axios.create({
baseURL:'//api.hanmeimei.com'
})
export {
mozleeAPI, jackmaAPI,hanmeimeiAPI
}
複製程式碼
- 常見需求還有取消請求,可以使用axios相關API。