1. 程式人生 > 程式設計 >在專案中封裝axios的實戰過程

在專案中封裝axios的實戰過程

目錄
  • 前言
  • axios封裝的好處
  • 封裝思路
  • 配置的優先順序
  • axios例項配置
    • 1、定義一些常規的配置
    • 2、請求前加一些我們需要的操作,
    • 3、請求返回後,新增攔截操作,
  • 請求介面方法統一管理
    • 最後放一下完整的示例!大家可以參考一下~
      • 總結

        前言

        在學習和做專案的時候經常會碰到axios,之前做的專案一般都是配置好axios,所以自己一直有個大概印象,最近有個機會自己可以手動配置axios,順便記錄分享一下~

        axios封裝的好處

        axios封裝的好處是統一處理,提高效率,便於維護。

        你可以像下面一樣這麼使用axios請求介面

        axios.get('http://localhost:10086/user?ID=12345')
          .then(response => {
            //成功後的操作...
          })
          .catch(error => {
            //失敗後的操作...
          });
        

        但是當介面請求多起來,需求多起來的時候,在專案中每個需要介面請求的地方寫一遍這樣的程式碼,這樣就會產生很多重複性的程式碼,降低我們的開發效率和提高維護成本。

        封裝思路

        我們需要一次性集中配置axios,讓配置適應我們專案的大部分場景。我們可以新建一個檔案,使用自定義配置新建一個 axios 例項,然後對例項進行基本配置,在請求前(請求體處理),請求後(返回的結果處理)等這些階段新增一些我們需要的處理,然後將其匯出使用。

        配置的優先順序

        配置會以一個優先順序進行合併。這個順序是:在lib/defaults.js找到的庫的預設值,然後是例項的defaults屬性,最後是請求的config引數。(這樣有些特殊的場景我們也可以單獨處理)

        node_modules資料夾下axios庫檔案下的lib/defaults.js。

        在專案中封裝axios的實戰過程

        自定義例項預設值

        const instance = axios.create({
          baseURL: 'https://api.example.com'
        });
        

        請求的config引數

        axios({   
        method:'get',url:'http://bit.ly/2mTM3nY',responseType:'stream' }).then(function(response) {   response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) });
        

        axios例項配置

        1、定義一些常規的配置

        設定BaseUrl

        baseUrl一般有分為生產、開發、測試等多個地址,我們可以弄一個config.js進行存放,如果是或react我們可以新建env等檔案進行存放,下面的baseUrl是使用react的環境變數的。

        • 設定timeout請求超時的時間
        • 設定資料請求的格式Content-Type(有 application/x-www-form-urlencoded、multipart/form-data、application/json...)等等
        import axios from 'axios'
        
        export const request = createAxiosInstance()
        
        function createAxiosInstance () {
          const instance = axios.create({
            baseURL: process.env.REACT_APP_BASE_URL,timeout: 5000,headers: {
              // 可定義統一的請求頭部
              post: {
                'Content-Type': 'application/json'
              }
              ...
            }
          })
          return instance
        }
        

        2、請求前加一些我們需要的操作,

        比如需要在請求頭裡新增token

        請求引數判空處理

        (下圖的例子傳了空的name和personId,這種會引起歧義,究竟是要獲取引數值為空還是忽略這些引數呢,有一些後端會進行一些處理,但前端還是盡http://www.cppcns.com量避免~)

        在專案中封裝axios的實戰過程

        每次介面請求時開啟loading動畫效果等等

          // 新增請求攔截器(在傳送請求之前做些什麼)
          instance.interceptors.request.use((config) => {
              //可新增開啟loading效果的函式
              loading.open()  
              //token 存在就新增到請求頭裡
              token && (config.headers.Authorization = token)
             // 過濾請求引數中的 null undefined ''的函式
              cleanObject()
              return config
          })
        

        3、請求返回後,新增攔截操作,

        • 處理成功返回的資料

        比如後端返回的data資料可能嵌套了很多層,你可以直接返回你需要的data資料,這樣業務程式碼就可以直接拿到最終的資料,而不用每次去解構之類的。

        • 統一處理失敗後的異常報錯

        介面請求有成功也有失敗,如果你不想在每寫一個介面請求的時候都需要去寫一遍失敗的邏輯程式碼,並且幾乎都是重複的時候,那你可以在這裡集中進行介面的統一的異常處理。如判斷狀態碼或後端自定義的code,並把後端返回的錯誤提示顯示出來。

         // 新增響應攔截器(對響應資料做點什麼)
          instance.interceptors.response.use((response) => {
           //可新增關閉loading效果的函式
              loading.close()  
              //解構出返回結果的資料
              const res = response.data
              //對自定義code碼進行判斷,將成功的資料返回出去
              const validateStatus = /^(2|3)\d{2}$/ //code為2或3開頭的視作請求成功
              if (validateStatus.test(res.code)) {
                return res      //直接return出去我們需要的data
              }
              //判斷失敗的code碼並作出提示等操作
              if (res.code === 401) {
                message.error(res.msg)
              } else {
                message.warning(res.msg)
              }
              return Promise.reject(res)
              },(error) => {
              loading.close() 
              if (error.response.status === 401) {
                message.error('token失效,請重新登入!')
                removeStorageToken()
                setTimeout(() => {
                  window.location.href = '/login'
                },2000)
              } else {
                if (!window.navigator.onLine) {
                  message.warning('網路異常,請檢查網路是否正常連線')
                } else if (error.code === 'ECONNABORTED') {
                  message.warning('請求超時')
              客棧  } else {
                  message.warning('伺服器異常,請聯絡管理員')
                }
              }
              return Promise.reject(error) // 將錯誤繼續返回給到具體頁面
            }
              )
        

        上面有根據HTTP狀態碼和自定義code做的一些錯誤處理,這裡進行了錯誤攔截後,頁面進行業務介面呼叫的時候就不用再每次進行錯誤提示處理。當然要根據不同專案需求進行配置。

        請求介面方法統一管理

        一般我們會把所有的介面請求方法寫在一起進行統一管理,後期更改的時候也方便查詢維護。

        在專案中封裝axios的實戰過程

        我們可以新建一個管理api請求的資料夾(如apiList),裡面放我們各種請求檔案(這裡按功能分)。如user.js就存放使用者相關的請求,其他類推。然後頁面就可以直接引用方法進行介面呼叫。

        import { request } from '../axios'
        
        // 獲取使用者資訊
        export function getUserInfo (userId) {
          return request.get(`/sys/user/info/${userId}`)
        }
        

        在元件或頁面直接呼叫方法就可以了~

        最後放一下完整的示例!大家可以參考一下~

        這個示例配置適用於vue或react,當然每個專案的配置都會有些不同,小夥伴要根據自己專案進行修改配置和擴充~

        import axios from 'axios'
        
        export const request = createAxiosInstance()
        
        function createAxiosInstance () {
          const instance = axios.create({
            baseURL: process.env.REACT_APP_BASE_URL,headers: {
              // 可定義統一的請求頭部xXjcCCKyhW
              post: {
                'Content-Type': 'application/json'
              }
              ...
            }
          })
           // 新增請求攔截器(在傳送請求之前做些什麼)
          instance.interceptors.request.use((config) => {
              //可新增開啟loading效果的函式
              loading.open()  
              //token 存在就新增到請求頭裡
              token && (config.headers.Authorization = token)
             // 過濾請求引數中的 null undefined ''的函式
              cleanObject()
              return config
          })
          // 新增響應攔截器(對響應資料做點什麼)
          instance.interceptors.response.use((response) => {
           //可新增關閉loading效果的函式
              loading.close()  
              //解構出返回結果的資料
              const res = response.data
              //對自定義code碼進行判斷,將成功的資料返回出去
              const validateStatus = /^(2|3)\d{2}$/ //code為2或3開頭的視作請求成功
              if (validateStatus.test(res.code)) {
                return res
              }
              //判斷失敗的code碼並作出提示等操作
              if (res.code === 401) {
                message.error(res.msg)
              } else {
                message.warning(res.msg)
              }
              return Promise.reject(res)
              },(error) => {
              loading.close()  //可新增關閉loading效果的函式
              if (error.response.status === 401) {
                message.error('token失效,請重新登入!')
                removeStorageToken()
                setTimeout(() => {
                  window.location.href = '/login'
                },2000)
              } else {
                if (!window.navigator.onLine) {
                  message.warning('網路異常,請檢查網路是否正常連線')
                } else if (error.code === 'ECONNABORTED') {
                 xXjcCCKyhW message.warning('請求超時')
                } else {
                  message.warning('伺服器異常,請聯絡管理員')
                }
              }
              return Promise.reject(error) // 將錯誤繼續返回給到具體頁面
            }
              )
          
          return instance
        }
        

        總結

        到此這篇關於在專案中封裝axios的文章就介紹到這了,更多相關專案中封裝axios內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!