最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你詳細了解vue axios的封裝

 更新時間:2023年09月02日 11:22:44   作者:東方小月  
對請求的封裝在實際項目中是十分必要的,它可以讓我們統(tǒng)一處理 http 請求,比如做一些攔截,處理一些錯誤等,本篇文章將詳細介紹如何封裝 axios 請求,需要的朋友可以參考下

axios 封裝

對請求的封裝在實際項目中是十分必要的,它可以讓我們統(tǒng)一處理 http 請求。比如做一些攔截,處理一些錯誤等。本篇文章將詳細介紹如何封裝 axios 請求,具體實現的功能如下

  • 基本配置

    配置默認請求地址,超時等

  • 請求攔截

    攔截 request 請求,處理一些發(fā)送請求之前做的處理,譬如給 header 加 token 等

  • 響應攔截

    統(tǒng)一處理后端返回的錯誤

  • 全局 loading

    為所有請求加上全局 loading(可配置是否啟用)

  • 取消重復請求

當同樣的請求還沒返回結果再次請求直接取消

基礎配置

這里以 vue3 為例,首先安裝 axios,element-plus

npm i axios element-plus

在 src 下新建 http/request.ts 目錄用于寫我們的封裝邏輯,然后調用 aixos 的 create 方法寫一些基本配置

import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
const service = axios.create({
  method: 'get',
  baseURL: import.meta.env.VITE_APP_API, //.env中的VITE_APP_API參數
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
  timeout: 10000, //超時時間
});
export default service;

這樣便完成了 aixos 的基本配置,接下來我們可以在 http 下新建 api 目錄用于存放我們接口請求,比如在 api 下創(chuàng)建 login.ts 用于寫登錄相關請求方法,這里的/auth/login我已經用 nestjs 寫好了

import request from './request';
export const login = (data: any) => {
  return request({
    url: '/auth/login',
    data,
    method: 'post',
  });
};

然后可以在頁面進行調用

<script lang="ts" setup>
import { login } from '@/http/login';
const loginManage = async () => {
  const data = await login({
    username: '雞哥哥',
    password: '1234',
  });
  console.log(data);
};
loginManage();
</script>

結果打印如下

響應攔截器

我們可以看到返回的數據很多都是我們不需要的,我們需要的只有 data 中的數據,所以這時候我們便需要一個響應攔截器進行處理,同時在響應攔截器中我們不僅僅簡單處理這個問題,還需要對后端返回的狀態(tài)碼進行判斷,如果不是正確的狀態(tài)碼可以彈窗提示后端返回的描述(也可以自定義)

service.interceptors.response.use(
  (res: AxiosResponse<any, any>) => {
    const { data } = res;
    if (data.code != 200) {
      ElMessage({
        message: data.describe,
        type: 'error',
      });
      if (data.code === 401) {
        //登錄狀態(tài)已過期.處理路由重定向
        console.log('loginOut');
      }
      throw new Error(data.describe);
    }
    return data;
  },
  (error) => {
    let { message } = error;
    if (message == 'Network Error') {
      message = '后端接口連接異常';
    } else if (message.includes('timeout')) {
      message = '系統(tǒng)接口請求超時';
    } else if (message.includes('Request failed with status code')) {
      message = '系統(tǒng)接口' + message.substr(message.length - 3) + '異常';
    }
    ElMessage({
      message: message,
      type: 'error',
    });
    return Promise.reject(error);
  },
);

這里規(guī)定后臺 code 不是 200 的請求是異常的,需要彈出異常信息(當然這里由自己規(guī)定),同時 401 狀態(tài)表示登錄已過期,如果你需要更多的異常處理都可以寫在這里。注意這里都是對 code 狀態(tài)碼的判斷,這表示后臺返回的 http 的 status 都是 2xx 才會進入的邏輯判斷,如果后臺返回 status 異常狀態(tài)碼比如 4xx,3xx 等就會進入 error 里,可以在 error 里進行邏輯處理,這里要和后端小朋友約定好

請求攔截器

請求請求攔截器和響應攔截器類似,只不過是在請求發(fā)送之前我們需要做哪些處理,它的用法如下

service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    console.log(config);
    return config;
  },
  (error) => {
    console.log(error);
  },
);

我們可以看到 config 中包含了我們請求的一些信息像 headers,data 等等,我們是可以在這里對其進行修改的,比如我們在 headers 加一個 token

declare module "axios" {
  interface InternalAxiosRequestConfig<D = any, T = any> {
    isToken?: boolean;
  }
}
declare module "axios" {
  interface AxiosRequestConfig<D = any> {
    isToken?: boolean;
  }
}
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    const { isToken = true } = config;
    if (localStorage.getItem('token') && !isToken) {
      config.headers['Authorization'] =
        'Bearer ' + localStorage.getItem('token'); // 讓每個請求攜帶自定義token 請根據實際情況自行修改
    }
    return config;
  },
  (error) => {
    console.log(error);
  },
);

這里假設用戶登錄成功將 token 緩存到了 localStorage 中,接口是否需要 token 則是在請求的時候自己配置,比如 login 接口不加 token,注意這里需要給InternalAxiosRequestConfigAxiosRequestConfig加上自定義的字段,否則 TS 會報錯

export const login = (data: any) => {
  return request({
    url: '/auth/login',
    data,
    isToken: false,
    method: 'post',
  });
};

此時我們可以獲取到 config 中的 isToken 了

添加全局 loading

我們通常會在請求開始前加上 loading 彈窗,請求結束再進行關閉,實現其實很簡單,在請求攔截器中調用 ElLoading.service 實例,響應攔截器中 close 即可。但是這樣會出現一個問題,

當多個請求進入會開啟多個 loading 實例嗎? 這倒不會,因為在 element-plus 中的 ElLoading.service()是單例模式,只會開啟一個 loading。

上述問題雖然不需要我們考慮,但是還有一個問題

同時進來多個請求,此時 loading 已經開啟,假設 1 秒后多個請求中其中一個請求請求完成,按照上述邏輯會執(zhí)行 close 方法,但是還有請求未完成 loading 卻已經關閉,顯然這不符合我們的期望

因此,我們可以定義一個變量用于記錄正在請求的數量,當該變量為 1 時開啟 loading,當變量為 0 時關閉 loading,同樣的我們還定義了 config 中的 loading 讓開發(fā)者自己決定是否開啟 loading,實現如下

let requestCount = 0;
const showLoading = () => {
  requestCount++;
  if (requestCount === 1) loadingInstance();
};
const closeLoading = () => {
  requestCount--;
  if (requestCount === 0) loadingInstance().close();
};
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    const { loading = true, isToken = true } = config;
    return config;
  },
  (error) => {
    console.log(error);
  },
);
service.interceptors.response.use(
  (res: AxiosResponse<any, any>) => {
    const { data, config } = res;
    const { loading = true } = config;
    if (loading) closeLoading();
  },
  (error) => {
    closeLoading();
    return Promise.reject(error);
  },
);

取消重復請求

當同樣的請求還沒返回結果再次請求我們需要直接取消這個請求,通常發(fā)生在用戶連續(xù)點擊然后請求接口的情況,但是如果加了 loading 這種情況就不會發(fā)生。axios 中取消請求可以使用AbortController,注意這個 api 需要 axios 版本大于 v0.22.0 才可使用,低版本可以使用CancelToken,下面看一下AbortController使用方法

service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    const controller = new AbortController();
    const { loading = true, isToken = true } = config;
    config.signal = controller.signal;
    controller.abort();
    return config;
  },
  (error) => {
    console.log(error);
  },
);

這里是將 controller 的 signal 賦值給 config 的 sigal,然后執(zhí)行 controller 的 abort 函數即可取消請求

知道了如何取消 axios 請求,接下來我們就可以寫取消重復請求的邏輯了

當攔截到請求的時候,將 config 中的 data,url 作為 key 值,AbortController 實例作為 value 存在一個 map 中,判斷是否 key 值是否存在來決定是取消請求還是保存實例

const requestMap = new Map();
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    const controller = new AbortController();
    const key = config.data + config.url;
    config.signal = controller.signal;
    if (requestMap.has(key)) {
      requestMap.get(key).abort();
      requestMap.delete(key);
    } else {
      requestMap.set(key, controller);
    }
    return config;
  },
  (error) => {
    console.log(error);
  },
);

我們短時間內發(fā)送兩次請求就會發(fā)現有一個請求被取消了

到這里基本就完成了 axios 的封裝,下面是完整代碼,直接 CV,就可以摸魚一整天~

import axios, {
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import { ElMessage, ElLoading } from "element-plus";
const loadingInstance = ElLoading.service;
let requestCount = 0;
const showLoading = () => {
  requestCount++;
  if (requestCount === 1) loadingInstance();
};
const closeLoading = () => {
  requestCount--;
  if (requestCount === 0) loadingInstance().close();
};
const service: AxiosInstance = axios.create({
  method: "get",
  baseURL: import.meta.env.VITE_APP_API,
  headers: {
    "Content-Type": "application/json;charset=utf-8",
  },
  timeout: 10000,
});
//請求攔截
declare module "axios" {
  interface InternalAxiosRequestConfig<D = any, T = any> {
    loading?: boolean;
    isToken?: boolean;
  }
}
declare module "axios" {
  interface AxiosRequestConfig<D = any> {
    loading?: boolean;
    isToken?: boolean;
  }
}
const requestMap = new Map();
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    const controller = new AbortController();
    const key = config.data + config.url;
    config.signal = controller.signal;
    if (requestMap.has(key)) {
      requestMap.get(key).abort();
      requestMap.delete(key);
    } else {
      requestMap.set(key, controller);
    }
    console.log(123);
    const { loading = true, isToken = true } = config;
    if (loading) showLoading();
    if (localStorage.getItem("token") && !isToken) {
      config.headers["Authorization"] =
        "Bearer " + localStorage.getItem("token"); // 讓每個請求攜帶自定義token 請根據實際情況自行修改
    }
    return config;
  },
  (error) => {
    console.log(error);
  }
);
service.interceptors.response.use(
  (res: AxiosResponse<any, any>) => {
    const { data, config } = res;
    const { loading = true } = config;
    if (loading) closeLoading();
    if (data.code != 200) {
      ElMessage({
        message: data.describe,
        type: "error",
      });
      if (data.code === 401) {
        //登錄狀態(tài)已過期.處理路由重定向
        console.log("loginOut");
      }
      throw new Error(data.describe);
    }
    return data;
  },
  (error) => {
    closeLoading();
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口連接異常";
    } else if (message.includes("timeout")) {
      message = "系統(tǒng)接口請求超時";
    } else if (message.includes("Request failed with status code")) {
      message = "系統(tǒng)接口" + message.substr(message.length - 3) + "異常";
    }
    ElMessage({
      message: message,
      type: "error",
    });
    return Promise.reject(error);
  }
);
export default service;

以上就是一文帶你詳細了解vue axios的封裝的詳細內容,更多關于vue axios的封裝的資料請關注腳本之家其它相關文章!

相關文章

  • vue-devtools的安裝與使用教程

    vue-devtools的安裝與使用教程

    vue-devtools是一款基于chrome游覽器的插件,用于調試vue應用,這可以極大地提高我們的調試效率,這篇文章主要介紹了vue-devtools的安裝與使用教程,需要的朋友可以參考下
    2023-03-03
  • vue中使用路由改瀏覽器標題和圖標

    vue中使用路由改瀏覽器標題和圖標

    這篇文章主要介紹了vue中使用路由改瀏覽器標題和圖標,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue中實現左右聯動的效果

    vue中實現左右聯動的效果

    這篇文章主要介紹了vue中實現左右聯動的效果,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-06-06
  • Vue Getters和mapGetters的原理及使用示例詳解

    Vue Getters和mapGetters的原理及使用示例詳解

    Vuex的核心概念包括state、mutations、actions、getters和modules,今天,我們要深入探討其中一個關鍵部分:getters,以及它的相關輔助函數mapGetters,感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • Vue CLI3 如何支持less的方法示例

    Vue CLI3 如何支持less的方法示例

    這篇文章主要介紹了Vue CLI3 如何支持less的方法示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • vue中PC端使用高德地圖實現搜索定位、地址標記、彈窗顯示定位詳情(完整實例)

    vue中PC端使用高德地圖實現搜索定位、地址標記、彈窗顯示定位詳情(完整實例)

    這篇文章主要介紹了vue中PC端使用高德地圖實現搜索定位、地址標記、彈窗顯示定位詳情,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • vue中正確使用jsx語法的姿勢分享

    vue中正確使用jsx語法的姿勢分享

    這篇文章主要給大家介紹了關于vue中正確使用jsx的相關資料,JSX就是Javascript和XML結合的一種格式,React發(fā)明了JSX,利用HTML語法來創(chuàng)建虛擬DOM,當遇到<,JSX就當HTML解析,遇到{就當JavaScript解析,需要的朋友可以參考下
    2021-07-07
  • Vue使用Markdown文檔的示例

    Vue使用Markdown文檔的示例

    本文主要介紹了Vue使用Markdown文檔的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • 使用vue構建多頁面應用的示例

    使用vue構建多頁面應用的示例

    這篇文章主要介紹了使用vue構建多頁面應用的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下
    2020-10-10
  • 詳解Vue的監(jiān)聽屬性

    詳解Vue的監(jiān)聽屬性

    這篇文章主要為大家介紹了Vue的監(jiān)聽屬性,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11

最新評論

乌恰县| 浦城县| 伊宁县| 望奎县| 张家港市| 苏州市| 揭西县| 隆子县| 深水埗区| 马鞍山市| 玉环县| 高唐县| 嘉峪关市| 郓城县| 十堰市| 肇庆市| 泰和县| 江永县| 年辖:市辖区| 丹江口市| 五莲县| 丰城市| 前郭尔| 化隆| 墨江| 普安县| 合山市| 永顺县| 抚宁县| 清新县| 五大连池市| 桦甸市| 屏山县| 松溪县| 刚察县| 安远县| 南宫市| 大新县| 韩城市| 天镇县| 盐边县|