如何在V-cli封裝axios

1. 前言

hello,大家好,終于改完bug了。現(xiàn)在就開始來填坑了。在上一篇文章如何優(yōu)雅的使用Vuex中提到了使用axios插件封裝的一個統(tǒng)一的api庫。這篇文章就告訴大家如何封裝一個高效且簡易使用的api接口庫。

2. 為什么要封裝axios

剛回武漢的時候,接手一個新的項目,剛好這個項目也是用的axios與后臺進行及交互。具體的使用如下:

this.$axios.post(
   "/flow/getSchedule",
   this.$qs.stringify({
   userId: sessionStorage.getItem("userId"),
   pageNumber: pageNumber,
    pageSize: 4
   }))
   .then(resp => {
     this.tableData = resp.data.data;
     if (resp.data.data && resp.data.data.totalRow) {
       sessionStorage.setItem("scheduleCount", resp.data.data.totalRow);
     }
   });

當(dāng)然這種使用方法是再與后臺進行交互方面是沒有什么問題,但是在接口如果繁多并且不止再一個路由中使用時,一旦涉及到接口參數(shù)或者接口url地址的修改就會讓人很崩潰。并且也沒做統(tǒng)一的錯誤返回處理。前前后后接手的人也很多,所以就出現(xiàn)有的錯誤是彈窗提示,有的錯誤是頁面上方的message。有的就干脆不給提示。

我當(dāng)時也有問交接的同事為啥不做一下封裝,誰知道這位年輕人的一下就站起來,很快啊,上來就是一個不知道,翻手一個沒必要。我大意了,還沒來得及反駁,他人就溜了。為了后面自己不再踩坑,我就開始著手進行接口封裝。

3. 如何封裝axios

我這篇文章主要講解如何封裝axios,前提是你已經(jīng)熟悉了如何在v-cli腳手架中使用axios。還不了解的小伙伴可以移步axios官方文檔中學(xué)習(xí)axios的具體使用。

3-1. 修改基礎(chǔ)配置

  • 首先我們通過npm install axios命令下載axios插件
  • 然后在V-cli項目的main.js中引入
import axios from "axios";
Vue.prototype.$axios = axios;
  • 因為我們要在另外的js使用到$axios,所以這里要對main.js做一下修改,讓我們方便在其他非vue的文件中使用到Vue的實例。
export const app = new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");
  • 在其他文件中使用
// 這里的app就是Vue的實例了。
import { app } from "../main";

3.2. 創(chuàng)建api.js接口庫

3.2-1. 我們先在src文件夾下新增utils文件夾,新建api.js文件,編輯該文件

// 引入Vue實例對象
import { app } from "../main";
// 設(shè)置請求次數(shù)
let seq = 0;
// 設(shè)置基礎(chǔ)的統(tǒng)一接口方法
function axiosFn(options) {
  const config = {
    // 設(shè)置請求頭和默認請求方式
    // 默認為get請求
    method: "get",
    // 設(shè)置請求頭方式
    headers: {
      "Content-Type": "application/json;charset=utf-8",
    }
  };
  // 這里是對傳入的基礎(chǔ)配置進行處理
  for (const k in options) {
    if (k !== "param" && options.hasOwnProperty(k)) {
      config[k] = options[k];
    }
  }
  // 設(shè)置不同請求的參數(shù)
  .....
}

第一步主要是設(shè)置基礎(chǔ)的配置,包括請求頭請求方式的設(shè)置。

3.2-2. 根據(jù)請求方式和請求頭的不同設(shè)置不同傳參方式

// 設(shè)置不同請求的參數(shù)
if (
  config.method === "post"
  || config.method === "put"
  || config.method === "delete"
) {
  // 處理formData數(shù)據(jù)上傳
  if (config.headers["Content-Type"] === "multipart/form-data") {
    let formData = new FormData();
    Object.keys(options.param).forEach(key => {
      formData.append(key, options.param[key]);
    });
    config["data"] = formData;
  }
  // 請求頭為application/json的請求參數(shù)傳遞
  if (config.headers["Content-Type"] === "application/json;charset=utf-8") {
    config["data"] = options.param;
  }
  // 請求頭為application/x-www-form-urlencoded的請求參數(shù)傳遞
  if (config.headers["Content-Type"] === "application/x-www-form-urlencoded") {
    let postData = "";
    for (const key in options.param) {
      // 設(shè)置傳參為數(shù)組時使用jsonStringfy方法轉(zhuǎn)字符串
      if (
        Object.prototype.toString.apply(options.param[key])
        === "[object Array]"
        || Object.prototype.toString.apply(options.param[key])
        === "[object Object]"
      ) {
        options.param[key] = JSON.stringify(options.param[key]);
      }
      postData
        += encodeURIComponent(key)
        + "="
        + encodeURIComponent(options.param[key])
        + "&";
    }
    config["data"] = postData;
  }
} else if (config.method === "get") {
  // 有可能是字符串這里暫時先寫非全等
  if (options["param"] != undefined || options["param"] != null) {
    Object.keys(options["param"]).forEach(v => {
      if (
        Object.prototype.toString.apply(options["param"][v])
        === "[object Array]"
        || Object.prototype.toString.apply(options.param[v])
        === "[object Object]"
      ) {
        options["param"][v] = JSON.stringify(options["param"][v]);
      }
    });
  }
  config["params"] = options["param"];
}
// 攔截請求結(jié)果
.....

注意:這里的代碼本來是沒有這么復(fù)雜的,最開始只是設(shè)置最基礎(chǔ)的get,post請求參數(shù)。后來因為這個api庫被他們拿去用到各個項目中。出現(xiàn)了一大堆的問題。但是他們自己又不會針對項目作出對應(yīng)的修改。一出問題就噴我封裝的不對,難用。我又不能和他意氣用事。只有一張圖表達我的心情。

WechatIMG19.jpeg

咳咳,回到上述代碼中,這里get請求涉及到的處理不多,主要是其他的請求和請求頭的不同的處理

  • get請求處理:主要是對params參數(shù)中數(shù)組對象進行JSON.stringify轉(zhuǎn)碼就好了。這個是我們這邊的與后臺約定的統(tǒng)一處理方法。大家如果沒有這方面的需求可以不加這層判斷。
  • post/put/delete 請求處理:這里主要是對不同的請求頭進行處理。典型的處理是針對上傳文件的處理。通過這層處理后,我們在聯(lián)調(diào)上傳接口時,就不用使用new FormData()去包裝我們的上傳參數(shù)了。其它兩種也是常用的請求頭判斷和處理。這個就看具體的使用項目了。
    3.2-3. 設(shè)置axios攔截器
// 攔截請求結(jié)果
app.$axios.interceptors.response.use(
  function(response) {
    response.seq = seq;
    // 請求成功返回response
    if (response.status === 200) {
      if (response.data.code == 200) {
        return response;
      } else {
        return Promise.reject(response.data);
      }
      return response;
    }
  },
  function(error) {
    //判斷請求超時
    if (
      error.code === "ECONNABORTED"
      && error.message.indexOf("timeout") !== -1
    ) {
      app.$message.error("請求超時,請刷新頁面重試!");
      return;
    }
    error.seq = seq;
    return Promise.reject(error);
  }
);
seq++;
// return axios的new promise對象
return app.$axios(config).then(response => response.data);

注意點:

  • 這里的app就是main.jsexport出來的Vue實例。
  • 超時的判斷的錯誤碼要和后臺溝通好。
  • 最后把設(shè)置好的參數(shù)的axios方法return出去。

4. 如何使用封裝好的axios

4.1 export需要使用的接口

611605691090_.pic_hd.jpg

上圖是我們常用的登出接口,文件上傳接口,獲取用戶列表接口。

4.2 頁面中調(diào)用

image.png
image.png

這里需要注意2點

  1. notifyErrorremoveEmptyProp分別是處理接口返回錯誤信息的處理函數(shù),以及移除空的篩選列表篩選參數(shù)的方法。notifyError我們馬上介紹。而這個removeEmptyProp等我下次bug改完的。O(∩_∩)O。
  2. finallyPromise原型上的方法具體使用是和then,catch一致。這里我用它來處理無論接口請求成功或者失敗都關(guān)閉表格的加載loading。
    tipsPromise的用法詳解我先挖個坑。下次記起來就來填。

4.3 接口錯誤信息統(tǒng)一處理函數(shù)

image.png
// 引入錯誤信息描述碼
import {
  ERR_NET_FAIL,
  ERR_API_NO_LOGIN,
  message
} from "@/config/error";
// 統(tǒng)一錯誤處理接口
export function notifyError(err) {
  if (err.code) {
    // 登錄超時返回登錄頁面
    if (err.code === ERR_API_NO_LOGIN) {
      // 處理3個接口同時調(diào)用超時的問題
      if (app.$route.name === "SignIn") {
        return;
      }
      app.$message.error("登錄超時,請重新登錄!");
      app.$router.replace("/SignIn");
    } else if (err.code === ERR_NET_FAIL) {
      // 這里的Alert為封裝的插件彈窗
      app.$Alert(message[ERR_NET_FAIL]);
    } else {
      // 其它狀態(tài)嗎輸出錯誤提示
      app.$Alert(err.message || message[ERR_NET_FAIL]);
    }
  } else {
    app.$message.error(message[ERR_NET_FAIL]);
  }
}

這里沒有啥子好講了,就是通過不同的code碼來執(zhí)行不同的操作,彈窗顯示錯誤信息登錄超時跳轉(zhuǎn)登錄頁面的一些處理。

4. 結(jié)語

終于擼完了,希望這篇文章能幫助到正在使用axios的你。

最后,喜歡的話請點個贊唄????。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容