首頁 > 軟體

詳解如何消除axios攔截中的if

2022-04-17 13:00:54

基本攔截

axios的響應錯誤攔截中,難免會對error.status做各種各樣的if判斷,又或者switch。為了防止枯燥乏味的生活(給自己挖坑,換一種姿勢去寫攔截

// 以下大概是日常碰到的操作,攔截響應,判斷status做相應操作
function login () {
  console.log('登陸邏輯')
  return promise.reject(error)
}
// 新增響應攔截器
axios.interceptors.response.use(function (response) {
  // 對響應資料做點什麼
  return response;
}, function (error) {
  if (error.status === 401) {
    // 401重新登入
    console.log('未登陸')
    return login(error)
  } else if (error.status === 404) {
    console.log('404-什麼都沒')
    return promise.reject(error)
  } else if (error.status === 422) {
    console.log(error.response.data.message)
    return promise.reject(error)
  } else if (error.status === 500) {
    console.log('伺服器內部錯誤')
    return promise.reject(error)
  } else {
    // 其他請求,直接丟擲讓業務去處理
    return promise.reject(error)
  }
});

設計輪子

思考方向

首先思考下怎麼實現這個東西

  • 需要一個在內部消化if的邏輯判斷
  • 根據判斷去執行相應的邏輯,意味著我們要在內部維護一個邏輯陣列(以下稱為管道陣列),配合成功後即觸發對應管道。所以在開始呼叫函數去執行前,先要收集好管道。這個方法需要傳一個標記(用來判斷是否匹配)和回撥函數(匹配成功後的邏輯)
  • 除了傳標記,需要傳一個payload(例如攔截中的error)引數,payload可以讓我們在回撥函數做出更多的對應操作
  • 在最後再新增一個default函數來收集匹配失敗後的函數。

現在,已經在心中擬好了一個小輪子的五臟六腑。

輪子骨架

// 定義個一個class
class Enterclose {
  constructor () {
    // 維護管道陣列
    this.pond = {}
    // 預設管道
    this._default = null
  }
  /**
   * 收集管道
   * callback(payload)
   * @param {any} sign 標記
   * @param {Function|Object} callback 回撥函數|函數this
   * @return this
   * */
  use (sign, callback) {
    return this
  }
  /**
   * 收集匹配失敗的管道
   * callback(payload)
   * @param {Function} callback 回撥函數|函數this
   * @return this
   * */
  default (callback) {
    this._default = callback
    return this
  }
  /**
   * 執行管道流
   * @param {any} sign 標記
   * @param {any} payload
   * @return
   */
  start (sign, payload) {
  }
}

詳細實現

以上把基本的api骨架寫好,然後再一個一個慢慢實現內部的邏輯。

首先是use,用來收集管道,需求中標記是唯一的,所以我們的this.ponds的結構是{標記: callback}

use (sign, callback) {
    this.ponds[sign] = callback
    return this
}

其中我們需要一個方法用來啟動Enterclose

通過getCallback函數去篩選和標記匹配的管道,返回對應的函數。這樣一個消除if的小輪子就搞好啦

start (sign, payload) {
    const fn = this.getCallback(sign)
    if (fn) {
      return fn(payload)
    }
}
/**
* 根據標記獲取函數
* @param {*} sign 
* @return {Function}
*/
getCallback (sign) {
    const key = Object.keys(this.ponds).find(key => key === sign)
    if (key) {
      return this.ponds[key]
    } else if (this._default) {
      return this._default
    }
}

實踐

建立範例,用use和default收集管道,然後在攔截中通過start觸發判斷

const enterclose = new Enterclose()
// 收集管道
enterclose
.use(401, function (error) {
  console.log('未登陸')
  return login(error)
})
.use(404, function (error) {
  console.log('404-什麼都沒')
  return promise.reject(error)
})
.use(429, function (error) {
  console.log(error.response.data.message)
  return promise.reject(error)
})
.use(500, function (error) {
  console.log('伺服器內部錯誤')
  return promise.reject(error)
})
.default(function (error) {
  // 收集預設管道
  return promise.reject(error)
})
axios.interceptors.response.use(function (response) {
  // 對響應資料做點什麼
  return response;
}, function (error) {
  // 啟動
  return enterclose.start(error.status, error)
});

你也可以根據自己的場景做一些調整,例如支援Promise啊,或者說加一個finally函數,每次走管道最後都會呼叫這個回撥函數之類

總結

到此這篇關於如何消除axios攔截中if的文章就介紹到這了,更多相關消除axios攔截的if內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com