高手篇 【為何要再封裝 AJAX】?
前言
再封裝AJAX所帶來的好處是你想象不到的! 無論是對於程式碼的高效管理,還是系統的設計...其收益遠遠超出你的想象。更重要的一點是:別人一看你的程式碼心裡就有數了,高手,一定是高手...
為何需要在封裝
我們先來看看以下應用場景,專案中涉及100個AJAX
請求,其中:
- 其中60個需要在請求頭header設定token
headers: {token: token}
用於許可權校驗; - 其中20個為上傳EXCEL檔案需要在請求頭中設定Content-Type;
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary} `
}
複製程式碼
- ③最後20個請求用來
獲取檔案流
,需要指定接受型別responseType: 'blob'
- 需要對全域性發起request進行攔截並做非同步處理(強調:是非同步處理);
- 如果你的專案已經做到一半,現在後端要加上token許可權做認證;
上面說的 1、2、3可以在全域性
request
攔截中進行處理,但是代價極大,需要為這100個介面都做判斷再做相應處理... ;當然也可以不用全域性攔截,為每個介面都單獨定義,我相信有不少同學仍是這樣處理的,但是只要有改動,例如現在我要求所有的請求頭都新增一個引數,那就只能一個一個介面的改.....這不是我們想要的結果,所以 我們需要對AJAX再封裝!AJAX再封裝!AJAX再封裝!,因為相當重要,所以要多說幾遍....
針對第四種情況,在axios裡面如果對request只能做一些同步操作;做非同步,直接就報錯了... 但這也可以用封裝AJAX來實現!簡直就是黑魔法...厲害厲害...
封裝實現
封裝其實很簡單,就是對原來真正的AJAX套一個殼,這個殼就是一個函式! 在這個函式裡都幹了些什麼見不得人事呢?幹什麼都可以,上面說的1、 2、 3、 4、 5都可以在這裡悄悄的進行,那對原來的AJAX鏈式呼叫有影響嗎?答案是肯定的:沒有影響。 先來看看我在程式碼裡呼叫的AJAX:
_initEditParams () {
this.$axios ('Common/Permission/Get', {Id}).then(res => {
....
....
})
},
複製程式碼
是不是直接呼叫AJAX還要簡潔?是的,因為這裡把請求方法之類的配置項全放在封裝裡面進行了。
等一下...這裡使用的
this.$axios
方式呼叫的,好像和我使用的沒啥差別嘛... 是的,這裡也是通過Vue.prototype.$axios = axios
新增到vue全域性例項的,但這裡新增的axios
不是直接引入的axios外掛,而是一個方法
import {axios} from './utils/common'
Vue.prototype.$axios = axios
複製程式碼
當然。也可以不用新增到全域性例項裡面,可以在元件中通過
import
語法引入使用。當然是專案裡大量使用的封裝方法直接使用Vue.prototype
新增到vue
例項。接下來我們看看axios方法都做了些啥:
import Axios from 'axios'
import Store from '../vuex'
/*********************************
** Fn: axios
** Intro: 公用封裝的axios 已在main.js中進行 $axios代理
** Intro: Store.state.permission.constUrl 為公用的介面字首地址
** Intro: url 方法接受引數 為定義的 介面地址字尾
** Intro: data 方法接受引數 為定義的引數
** Author: zyx
*********************************/
export function axios (url, data) {
return new Promise((resolve, reject) => {
Axios({
url: `${Store.state.permission.constUrl}${url}`,
method: 'post',
data: data,
headers: {
token: Store.state.permission.token
}
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
複製程式碼
這個方法裡關鍵點就是
Promise
!只有Promise
能滿足鏈式呼叫。Promise
真是個好東西,具體的Promise
語法我就不再這裡說明了,因為說了也說不好。Promise
有三個狀態,pending、resolve和reject。妙處就在於可以一直讓Promise
處理pending狀態(可以理解為等待),心情好了,就resolve()
進行釋放,在.then()
裡面進行相應處理。心情不好就直接reject()
打回,那就在.catch()
處理。(提示:Promise
還可以用來做父子元件通訊,利用resolve()
)
點個贊給力鼓勵啦~
程式碼奉上
最後奉上我自己封裝的三個方法:
import Axios from 'axios'
import Store from '../vuex'
/*********************************
** Fn: axios
** Intro: 公用封裝的axios 已在main.js中進行 $axios代理
** Intro: Store.state.permission.constUrl 為公用的介面字首地址
** Intro: url 方法接受引數 為定義的 介面地址字尾
** Intro: data 方法接受引數 為定義的引數
** Author: zyx
*********************************/
export function axios (url, data) {
return new Promise((resolve, reject) => {
Axios({
url: `${Store.state.permission.constUrl}${url}`,
method: 'post',
data: data,
headers: {
token: Store.state.permission.token
}
// withCredentials: true
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
/********************************
** Fn: axiosImportFile
** Intro: 該方法用於匯入excel檔案 需改變content-type
** Author: zyx
*********************************/
export function axiosImportFile (url, data) {
return new Promise((resolve, reject) => {
Axios({
url: `${Store.state.permission.constUrl}${url}`,
method: 'post',
data: data,
headers: {
token: Store.state.permission.token,
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
}
// withCredentials: true
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
/**
* 專用於獲取excel 流
* responseType: 'blob'
* @param url
* @returns {Promise}
*/
export function axiosExcel (url, params) {
return new Promise((resolve, reject) => {
Axios({
url: `${Store.state.permission.constUrl}${url}`,
method: 'post',
headers: {
token: Store.state.permission.token
},
data: params,
responseType: 'blob'
// withCredentials: true
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
複製程式碼
個人其他文章推薦:
- 補充一點:IE9不支援AJAX請求頭,免費同學入坑。
- 實現一個可無限摺疊的table
- 當下拉列表資料過大時,該如何應對?
- Vue自定義指令實現input限制輸入正整數