国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

一篇文章帶你詳細(xì)了解axios的封裝

這篇具有很好參考價(jià)值的文章主要介紹了一篇文章帶你詳細(xì)了解axios的封裝。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

axios 封裝

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

  • 基本配置

    配置默認(rèn)請(qǐng)求地址,超時(shí)等

  • 請(qǐng)求攔截

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

  • 響應(yīng)攔截

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

  • 全局 loading

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

  • 取消重復(fù)請(qǐng)求

當(dāng)同樣的請(qǐng)求還沒(méi)返回結(jié)果再次請(qǐng)求直接取消

基礎(chǔ)配置

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

npm i axios element-plus

在 src 下新建 http/request.ts 目錄用于寫我們的封裝邏輯,然后調(diào)用 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參數(shù)
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
  timeout: 10000, //超時(shí)時(shí)間
});

export default service;

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

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

然后可以在頁(yè)面進(jìn)行調(diào)用

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

結(jié)果打印如下

一篇文章帶你詳細(xì)了解axios的封裝

響應(yīng)攔截器

我們可以看到返回的數(shù)據(jù)很多都是我們不需要的,我們需要的只有 data 中的數(shù)據(jù),所以這時(shí)候我們便需要一個(gè)響應(yīng)攔截器進(jìn)行處理,同時(shí)在響應(yīng)攔截器中我們不僅僅簡(jiǎn)單處理這個(gè)問(wèn)題,還需要對(duì)后端返回的狀態(tài)碼進(jìn)行判斷,如果不是正確的狀態(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)已過(guò)期.處理路由重定向
        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)接口請(qǐng)求超時(shí)';
    } 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ī)定后臺(tái) code 不是 200 的請(qǐng)求是異常的,需要彈出異常信息(當(dāng)然這里由自己規(guī)定),同時(shí) 401 狀態(tài)表示登錄已過(guò)期,如果你需要更多的異常處理都可以寫在這里。注意這里都是對(duì) code 狀態(tài)碼的判斷,這表示后臺(tái)返回的 http 的 status 都是 2xx 才會(huì)進(jìn)入的邏輯判斷,如果后臺(tái)返回 status 異常狀態(tài)碼比如 4xx,3xx 等就會(huì)進(jìn)入 error 里,可以在 error 里進(jìn)行邏輯處理,這里要和后端小朋友約定好

請(qǐng)求攔截器

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

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

一篇文章帶你詳細(xì)了解axios的封裝

我們可以看到 config 中包含了我們請(qǐng)求的一些信息像 headers,data 等等,我們是可以在這里對(duì)其進(jìn)行修改的,比如我們?cè)?headers 加一個(gè) 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'); // 讓每個(gè)請(qǐng)求攜帶自定義token 請(qǐng)根據(jù)實(shí)際情況自行修改
    }
    return config;
  },
  (error) => {
    console.log(error);
  },
);

這里假設(shè)用戶登錄成功將 token 緩存到了 localStorage 中,接口是否需要 token 則是在請(qǐng)求的時(shí)候自己配置,比如 login 接口不加 token,注意這里需要給InternalAxiosRequestConfigAxiosRequestConfig加上自定義的字段,否則 TS 會(huì)報(bào)錯(cuò)

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

一篇文章帶你詳細(xì)了解axios的封裝

此時(shí)我們可以獲取到 config 中的 isToken 了

添加全局 loading

我們通常會(huì)在請(qǐng)求開始前加上 loading 彈窗,請(qǐng)求結(jié)束再進(jìn)行關(guān)閉,實(shí)現(xiàn)其實(shí)很簡(jiǎn)單,在請(qǐng)求攔截器中調(diào)用 ElLoading.service 實(shí)例,響應(yīng)攔截器中 close 即可。但是這樣會(huì)出現(xiàn)一個(gè)問(wèn)題,

當(dāng)多個(gè)請(qǐng)求進(jìn)入會(huì)開啟多個(gè) loading 實(shí)例嗎? 這倒不會(huì),因?yàn)樵?element-plus 中的 ElLoading.service()是單例模式,只會(huì)開啟一個(gè) loading。

上述問(wèn)題雖然不需要我們考慮,但是還有一個(gè)問(wèn)題

同時(shí)進(jìn)來(lái)多個(gè)請(qǐng)求,此時(shí) loading 已經(jīng)開啟,假設(shè) 1 秒后多個(gè)請(qǐng)求中其中一個(gè)請(qǐng)求請(qǐng)求完成,按照上述邏輯會(huì)執(zhí)行 close 方法,但是還有請(qǐng)求未完成 loading 卻已經(jīng)關(guān)閉,顯然這不符合我們的期望

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

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ù)請(qǐng)求

當(dāng)同樣的請(qǐng)求還沒(méi)返回結(jié)果再次請(qǐng)求我們需要直接取消這個(gè)請(qǐng)求,通常發(fā)生在用戶連續(xù)點(diǎn)擊然后請(qǐng)求接口的情況,但是如果加了 loading 這種情況就不會(huì)發(fā)生。axios 中取消請(qǐng)求可以使用AbortController,注意這個(gè) 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 函數(shù)即可取消請(qǐng)求

一篇文章帶你詳細(xì)了解axios的封裝

知道了如何取消 axios 請(qǐng)求,接下來(lái)我們就可以寫取消重復(fù)請(qǐng)求的邏輯了

當(dāng)攔截到請(qǐng)求的時(shí)候,將 config 中的 data,url 作為 key 值,AbortController 實(shí)例作為 value 存在一個(gè) map 中,判斷是否 key 值是否存在來(lái)決定是取消請(qǐng)求還是保存實(shí)例

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);
  },
);

我們短時(shí)間內(nèi)發(fā)送兩次請(qǐng)求就會(huì)發(fā)現(xiàn)有一個(gè)請(qǐng)求被取消了

到這里基本就完成了 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,
});
//請(qǐng)求攔截

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"); // 讓每個(gè)請(qǐng)求攜帶自定義token 請(qǐng)根據(jù)實(shí)際情況自行修改
    }

    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)已過(guò)期.處理路由重定向
        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)接口請(qǐng)求超時(shí)";
    } 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;

微信掃碼關(guān)注公眾號(hào)web前端進(jìn)階每日更新最新前端技術(shù)文章,你想要的都有!
一篇文章帶你詳細(xì)了解axios的封裝文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-471634.html

到了這里,關(guān)于一篇文章帶你詳細(xì)了解axios的封裝的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C++】一篇文章帶你深入了解list

    【C++】一篇文章帶你深入了解list

    list是可以在常數(shù)范圍內(nèi)在任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。 list的底層是雙向鏈表結(jié)構(gòu),雙向鏈表中每個(gè)元素存儲(chǔ)在互不相關(guān)的獨(dú)立節(jié)點(diǎn)中,在節(jié)點(diǎn)中通過(guò)指針指向其前一個(gè)元素和后一個(gè)元素。 list與forward_list非常相似:最主要的不同在

    2024年04月23日
    瀏覽(30)
  • 【C++】一篇文章帶你深入了解string

    【C++】一篇文章帶你深入了解string

    C語(yǔ)言中,字符串是以’\\0’結(jié)尾的一些字符的集合,為了操作方便,C標(biāo)準(zhǔn)庫(kù)中提供了一些str系列的庫(kù)函數(shù),但是這些庫(kù)函數(shù)與字符串是分離開的,不太符合OOP的思想,而且底層空間需要用戶自己管理,稍不留神可能還會(huì)越界訪問(wèn)。 string的文檔介紹 字符串是表示字符序列的類

    2024年04月08日
    瀏覽(27)
  • 【C++】一篇文章帶你深入了解vector

    【C++】一篇文章帶你深入了解vector

    vector的文檔介紹 vector是表示可變大小數(shù)組的序列容器。 就像數(shù)組一樣,vector也采用的連續(xù)存儲(chǔ)空間來(lái)存儲(chǔ)元素。也就是意味著可以采用下標(biāo)對(duì)vector的元素進(jìn)行訪問(wèn),和數(shù)組一樣高效。但是又不像數(shù)組,它的大小是可以動(dòng)態(tài)改變的,而且它的大小會(huì)被容器自動(dòng)處理。 本質(zhì)講,

    2024年04月22日
    瀏覽(36)
  • 一篇文章帶你了解 什么是u(ustd)帶你了解他的前世今生

    一篇文章帶你了解 什么是u(ustd)帶你了解他的前世今生

    在數(shù)字貨幣的繁榮世界中,USDT無(wú)疑是其中一位重要的角色。它的前世今生,是一個(gè)從無(wú)到有,從小到大,經(jīng)歷了種種波折和爭(zhēng)議的故事。 2014年11月下旬,一個(gè)名為Realcoin的注冊(cè)地為馬恩島和香港的公司決定改變自己的名字,取名為Tether。這個(gè)決定預(yù)示著一種新的數(shù)字貨幣即將

    2024年01月23日
    瀏覽(23)
  • WAF是什么?一篇文章帶你全面了解WAF

    Web應(yīng)用程序防火墻(Web Application Firewall,WAF)是一種用于保護(hù)Web應(yīng)用程序的安全設(shè)備。Web應(yīng)用程序是指通過(guò)Web瀏覽器或其他Web客戶端訪問(wèn)的應(yīng)用程序。WAF的目的是保護(hù)Web應(yīng)用程序免受黑客、網(wǎng)絡(luò)攻擊和數(shù)據(jù)泄漏等安全威脅的攻擊。 在這篇文章中,我們將深入探討WAF的工作原理

    2024年02月10日
    瀏覽(23)
  • 【網(wǎng)絡(luò)安全】一篇文章帶你了解CTF那些事兒

    【網(wǎng)絡(luò)安全】一篇文章帶你了解CTF那些事兒

    CTF(Capture The Flag)中文一般譯作奪旗賽,在網(wǎng)絡(luò)安全領(lǐng)域中指的是網(wǎng)絡(luò)安全技術(shù)人員之間進(jìn)行技術(shù)競(jìng)技的一種比賽形式。CTF起源于1996年DEFCON全球黑客大會(huì),以代替之前黑客們通過(guò)互相發(fā)起真實(shí)攻擊進(jìn)行技術(shù)比拼的方式。已經(jīng)成為全球范圍網(wǎng)絡(luò)安全圈流行的競(jìng)賽形式,2013年全

    2024年02月08日
    瀏覽(24)
  • 【云原生】什么是云原生?如何學(xué)習(xí)云原生?一篇文章帶你了解云原生

    【云原生】什么是云原生?如何學(xué)習(xí)云原生?一篇文章帶你了解云原生

    云原生,相信這個(gè)名詞大家并不陌生;云原生在近期可謂是爆火,伴隨云計(jì)算的滾滾浪潮,云原生(CloudNative)的概念應(yīng)運(yùn)而生,云原生很火,火得一塌糊涂。可是現(xiàn)在很多人還是不知道什么是云原生,所以今天我們就來(lái)聊一聊近期很火的這個(gè)名詞:云原生吧 。 大家平時(shí)經(jīng)常提

    2024年02月02日
    瀏覽(31)
  • 一篇文章帶你了解什么是云計(jì)算,SaaS PaaS IaaS的區(qū)別

    一篇文章帶你了解什么是云計(jì)算,SaaS PaaS IaaS的區(qū)別

    目錄 一、本地部署 vs 云計(jì)算 彈性 運(yùn)維成本 數(shù)據(jù)安全 二、SaaS PaaS IaaS的區(qū)別 在了解云計(jì)算之前,我們先要了解什么是“計(jì)算”,支撐計(jì)算我們需要硬件基礎(chǔ)設(shè)施和軟件環(huán)境。 硬件包括服務(wù)器、存儲(chǔ)、網(wǎng)絡(luò)等...? 軟件環(huán)境包括數(shù)據(jù)庫(kù)、中間件、操作系統(tǒng)等... 云就是個(gè)地理概

    2024年04月27日
    瀏覽(32)
  • 一篇文章帶你了解抖音來(lái)客功能的使用方法和注意事項(xiàng)

    一篇文章帶你了解抖音來(lái)客功能的使用方法和注意事項(xiàng)

    抖音是近年來(lái)備受歡迎的社交媒體平臺(tái)之一,其中的“來(lái)客”功能更是讓許多人喜愛(ài)。那么什么是抖音來(lái)客呢?抖音來(lái)客是指在直播過(guò)程中,可以邀請(qǐng)其他抖音用戶進(jìn)行互動(dòng)和參與,從而增加直播的熱度和粉絲數(shù)量。下面不若與眾科技就來(lái)介紹一下抖音來(lái)客的具體使用方法和

    2024年02月08日
    瀏覽(25)
  • 【Java遞歸】一篇文章帶你了解,什么是遞歸 ,遞歸的特點(diǎn),遞歸應(yīng)用場(chǎng)景,遞歸練習(xí)題

    【Java遞歸】一篇文章帶你了解,什么是遞歸 ,遞歸的特點(diǎn),遞歸應(yīng)用場(chǎng)景,遞歸練習(xí)題

    博主: 東方幻想郷 專欄分類: Java | 從入門到入墳 ??遞歸是一種在方法通過(guò) 調(diào)用自身 來(lái)解決某些問(wèn)題的技術(shù),它可以將一些問(wèn)題,分為更小,更細(xì)類似的子問(wèn)題,逐步解決, 直到問(wèn)題被簡(jiǎn)化到某個(gè)基本情況 ,最后可以直接拿到答案。 遞歸是一種函數(shù)調(diào)用自身的方法 遞歸

    2024年02月06日
    瀏覽(45)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包