1. 程式人生 > >高手篇 【為何要再封裝 AJAX】?

高手篇 【為何要再封裝 AJAX】?

前言

封裝AJAX所帶來的好處是你想象不到的! 無論是對於程式碼的高效管理,還是系統的設計...其收益遠遠超出你的想象。更重要的一點是:別人一看你的程式碼心裡就有數了,高手,一定是高手...

為何需要在封裝

我們先來看看以下應用場景,專案中涉及100個AJAX請求,其中:

  1. 其中60個需要在請求頭header設定token headers: {token: token}用於許可權校驗;
  2. 其中20個為上傳EXCEL檔案需要在請求頭中設定Content-Type;
      headers: {
        'Content-Type': `multipart/form-data; boundary=${data._boundary}
` } 複製程式碼
  1. ③最後20個請求用來獲取檔案流,需要指定接受型別responseType: 'blob'
  2. 需要對全域性發起request進行攔截並做非同步處理強調:是非同步處理);
  3. 如果你的專案已經做到一半,現在後端要加上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有三個狀態,pendingresolvereject。妙處就在於可以一直讓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)
    })
  })
}
複製程式碼

個人其他文章推薦: