Axios 請求取消:從原理到實踐

Axios 請求取消:從原理到實踐

在現代前端開發中,網絡請求是不可或缺的一部分。Axios 是一個基于 Promise 的 HTTP 客戶端,廣泛應用于瀏覽器和 Node.js 環境中。然而,在某些場景下,我們可能需要取消正在進行的請求,例如用戶在請求完成前跳轉到其他頁面,或者重復觸發相同的請求時取消之前的請求。本文將深入探討 Axios 請求取消的原理,并通過一個二次封裝的例子來演示如何實現請求取消。

1. 請求取消的原理

Axios 的請求取消功能依賴于 CancelTokenCancelToken 是一個用于取消請求的令牌,它可以通過 CancelToken.source() 方法創建。每個 CancelToken 實例都有一個 token 和一個 cancel 方法。當調用 cancel 方法時,與該 token 關聯的請求將被取消。

1.1 CancelToken 的工作原理

  1. 創建 CancelToken: 通過 CancelToken.source() 方法創建一個 CancelToken 實例,該實例包含一個 token 和一個 cancel 方法。
  2. 關聯請求: 在發起請求時,將 token 傳遞給 Axios 請求配置中的 cancelToken 字段。
  3. 取消請求: 當需要取消請求時,調用 cancel 方法,Axios 會中斷與該 token 關聯的請求。

1.2 取消請求的流程

  1. 用戶觸發某個操作,發起一個請求。
  2. 在請求完成之前,用戶觸發了另一個操作,需要取消之前的請求。
  3. 調用 cancel 方法,Axios 中斷之前的請求。
  4. 發起新的請求。

2. 二次封裝 Axios 實現請求取消

為了更好地管理請求取消邏輯,我們可以對 Axios 進行二次封裝。以下是一個簡單的封裝示例,展示了如何在封裝中實現請求取消功能。


1. 代碼結構分析

1.1 Axios 實例的創建

const instance: AxiosInstance = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL,timeout: 10000,headers: {'Content-Type': 'application/json',},
});
  • baseURL: 從環境變量中獲取 API 的基礎 URL。
  • timeout: 設置請求超時時間為 10 秒。
  • headers: 設置默認請求頭為 application/json

通過 axios.create 創建了一個 Axios 實例 instance,后續的所有請求都將基于這個實例。


1.2 取消令牌的管理

const cancelTokenMap = new Map<string, CancelTokenSource>();
  • cancelTokenMap: 使用 Map 數據結構來存儲每個請求的取消令牌。鍵是請求的 URL,值是對應的 CancelTokenSource
  • 作用: 通過 URL 快速查找和取消對應的請求。

1.3 請求攔截器

instance.interceptors.request.use((config) => {// 添加 token 到請求頭const token = localStorage.getItem('token');if (token) {config.headers = config.headers || {};config.headers.Authorization = `Bearer ${token}`;}return config;},(error) => {return Promise.reject(error);}
);
  • 功能: 在請求發送前,檢查本地存儲中是否存在 token,如果存在則將其添加到請求頭中。
  • 作用: 實現全局的請求頭管理,例如身份驗證。

1.4 響應攔截器

instance.interceptors.response.use((response: AxiosResponse) => {// 清理已完成的請求記錄const url = response.config.url;if (url && cancelTokenMap.has(url)) {cancelTokenMap.delete(url);}// 處理全局響應邏輯if (response.data.code !== 0) {return Promise.reject(response.data);}return response.data;},(error) => {// 清理失敗的請求記錄const url = error.config?.url;if (url && cancelTokenMap.has(url)) {cancelTokenMap.delete(url);}// 處理全局錯誤if (error.response?.status === 401) {// 處理未授權window.location.href = '/login';}return Promise.reject(error);}
);
  • 功能:
    • 在請求成功時,清理 cancelTokenMap 中對應的請求記錄。
    • 在請求失敗時,清理 cancelTokenMap 中對應的請求記錄,并根據狀態碼處理全局錯誤(例如未授權時跳轉到登錄頁)。
  • 作用: 實現全局的響應和錯誤處理邏輯。

1.5 封裝的請求方法

const http = {get: <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.get(url, { ...config, cancelToken: source.token });},post: <T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.post(url, data, { ...config, cancelToken: source.token });},put: <T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.put(url, data, { ...config, cancelToken: source.token });},delete: <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.delete(url, { ...config, cancelToken: source.token });},// 取消指定請求cancelRequest: (url: string) => {const source = cancelTokenMap.get(url);if (source) {source.cancel(`Request canceled: ${url}`);cancelTokenMap.delete(url);}},// 取消所有請求cancelAllRequests: () => {cancelTokenMap.forEach((source, url) => {source.cancel(`Request canceled: ${url}`);cancelTokenMap.delete(url);});},
};
  • 功能:
    • 封裝了 getpostputdelete 方法,每個方法都會為請求創建一個 CancelToken,并將其存儲到 cancelTokenMap 中。
    • 提供了 cancelRequestcancelAllRequests 方法,用于取消指定請求或所有請求。
  • 作用: 簡化請求調用,并提供靈活的請求取消功能。

2. 請求取消的實現原理

2.1 CancelToken 的作用

  • CancelToken.source(): 創建一個 CancelTokenSource 對象,包含 tokencancel 方法。
  • token: 用于關聯請求。
  • cancel: 用于取消請求。

2.2 請求取消的流程

  1. 發起請求時,創建一個 CancelTokenSource,并將其存儲到 cancelTokenMap 中。
  2. 如果需要取消請求,調用 cancelRequestcancelAllRequests 方法。
  3. 調用 cancel 方法后,Axios 會中斷與該 token 關聯的請求,并拋出一個 Cancel 錯誤。
  4. 在響應攔截器中,清理已完成的請求記錄。

3. 使用場景

3.1 取消重復請求

當用戶快速點擊按鈕多次觸發相同的請求時,可以通過 cancelRequest 方法取消之前的請求,只保留最后一次請求。

http.get('/api/data').then((data) => console.log(data)).catch((error) => {if (axios.isCancel(error)) {console.log('Request canceled:', error.message);} else {console.error('Error:', error);}});// 取消之前的請求
http.cancelRequest('/api/data');

3.2 頁面跳轉時取消請求

當用戶跳轉到其他頁面時,可以通過 cancelAllRequests 方法取消所有未完成的請求,避免無效請求占用資源。

window.addEventListener('beforeunload', () => {http.cancelAllRequests();
});

完整代碼

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelTokenSource } from 'axios';// 創建axios實例
const instance: AxiosInstance = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL,timeout: 10000,headers: {'Content-Type': 'application/json',},
});// 創建一個Map來存儲取消令牌
const cancelTokenMap = new Map<string, CancelTokenSource>();// 請求攔截器
instance.interceptors.request.use((config) => {// 在這里可以添加token等全局請求頭const token = localStorage.getItem('token');if (token) {config.headers = config.headers || {};config.headers.Authorization = `Bearer ${token}`;}return config;},(error) => {return Promise.reject(error);}
);// 響應攔截器
instance.interceptors.response.use((response: AxiosResponse) => {// 清理已完成的請求記錄const url = response.config.url;if (url && cancelTokenMap.has(url)) {cancelTokenMap.delete(url);}// 在這里處理全局響應邏輯if (response.data.code !== 0) {return Promise.reject(response.data);}return response.data;},(error) => {// 清理失敗的請求記錄const url = error.config?.url;if (url && cancelTokenMap.has(url)) {cancelTokenMap.delete(url);}// 在這里處理全局錯誤if (error.response?.status === 401) {// 處理未授權window.location.href = '/login';}return Promise.reject(error);}
);// 封裝請求方法
const http = {get: <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.get(url, { ...config, cancelToken: source.token });},post: <T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.post(url, data, { ...config, cancelToken: source.token });},put: <T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.put(url, data, { ...config, cancelToken: source.token });},delete: <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {const source = axios.CancelToken.source();cancelTokenMap.set(url, source);return instance.delete(url, { ...config, cancelToken: source.token });},// 添加取消請求的方法// http.cancelRequest('/api/some-endpoint');cancelRequest: (url: string) => {const source = cancelTokenMap.get(url);if (source) {source.cancel(`Request canceled: ${url}`);cancelTokenMap.delete(url);}},// 取消所有請求cancelAllRequests: () => {cancelTokenMap.forEach((source, url) => {source.cancel(`Request canceled: ${url}`);cancelTokenMap.delete(url);});},
};export default http;

4. 總結

通過二次封裝 Axios,我們實現了一個功能強大且易于使用的 HTTP 客戶端。它不僅支持全局的請求和響應攔截,還提供了靈活的請求取消功能,適用于多種場景。希望本文能幫助你更好地理解和使用 Axios 的請求取消功能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/72355.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/72355.shtml
英文地址,請注明出處:http://en.pswp.cn/web/72355.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot對接twilio發送郵件信息

要在Spring Boot應用程序中對接Twilio發送郵件信息&#xff0c;您可以使用Twilio的SendGrid API。以下是一個簡單的步驟指南&#xff0c;幫助您完成這一過程&#xff1a; 1. 創建Twilio賬戶并獲取API密鑰 注冊一個Twilio賬戶&#xff08;如果您還沒有的話&#xff09;。在Twi…

【最后203篇系列】015 幾種消息隊列的思考

背景 隊列還是非常重要的中間件&#xff0c;可以幫助我們&#xff1a;提高處理效率、完成更復雜的處理流程 最初&#xff0c;我覺得只要掌握一種消息隊列就夠了&#xff0c;現在想想挺好笑的。 過去的探索 因為我用python&#xff0c;而rabbitmq比較貼合快速和復雜的數據處…

TensorFlow 與 TensorFlow Lite:核心解析與層應用

1. 引言 TensorFlow 是 Google 開發的開源機器學習框架&#xff0c;支持從數據預處理、模型訓練到推理部署的完整生命周期。然而&#xff0c;在嵌入式和移動設備上&#xff0c;原生 TensorFlow 過于龐大&#xff0c;因此 Google 推出了輕量級版本——TensorFlow Lite&#xff…

DeepSeek大模型在政務服務領域的應用

DeepSeek大模型作為國產人工智能技術的代表&#xff0c;近年來在政務服務領域的應用呈現多點開花的態勢。通過多地實踐&#xff0c;該技術不僅顯著提升了政務服務的效率與智能化水平&#xff0c;還推動了政府治理模式的創新。以下從技術應用場景、典型案例及發展趨勢三個維度進…

電子電氣架構 --- 分布到集中的動カ系統及基于域控制器的架構

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 所有人的看法和評價都是暫時的,只有自己的經歷是伴隨一生的,幾乎所有的擔憂和畏懼,都是來源于自己的想象,只有你真的去做了,才會發現有多快樂。…

深入理解C/C++堆數據結構:從原理到實戰

一、堆的本質與特性 1.1 什么是堆數據結構&#xff1f; 堆&#xff08;Heap&#xff09;是一種特殊的完全二叉樹&#xff0c;它滿足以下核心性質&#xff1a; 堆序性&#xff1a;每個節點的值都滿足特定順序關系 結構性&#xff1a;完全二叉樹的結構特性&#xff08;除最后一…

Python學習第十七天

Django框架-SQLite3 介紹 Django內置了對 SQLite3 數據庫的支持。SQLite3 是一個輕量級的嵌入式數據庫引擎&#xff0c;非常適合開發、測試和小型項目。以下是關于 Django 中 SQLite3 的介紹和應用指南。&#xff08;除了這些還支持mysql、oracle以及其他查詢文檔&#xff0c;…

Docker 》》Docker Compose 》》network 網絡 compose

docker 默認的網絡 三種模式 # 列出所有當前主機上或Swarm集群上的網絡 docker network ls#查看網絡詳情 docker network inspect network名稱# 清除未使用的docker網絡 docker network prune -f# 創建網絡 ocker network create -d bridge 網絡名稱 docker network create –s…

Python數字信號處理之最佳等波紋濾波器階數估計原理

Matlab中的階數估計函數 在MATLAB中&#xff0c;使用firpmord函數可以估算等波紋FIR濾波器的最小階數。該方法基于Parks-McClellan算法&#xff0c;通過通帶和阻帶的頻率邊界、幅度響應及允許的最大誤差來自動計算參數。 rp 3; % Passband ripple in dB rs 40; …

JumpServer基礎功能介紹演示

堡壘機可以讓運維人員通過統一的平臺對設備進行維護&#xff0c;集中的進行權限的管理&#xff0c;同時也會對每個操作進行記錄&#xff0c;方便后期的溯源和審查&#xff0c;JumpServer是由飛致云推出的開源堡壘機&#xff0c;通過簡單的安裝配置即可投入使用&#xff0c;本文…

C++和C的區別

C和C語言雖然共享相似的語法&#xff0c;但在設計理念和功能特性上有顯著區別。以下是兩者的主要差異&#xff1a; 1. 編程范式 C&#xff1a;純過程式編程&#xff0c;強調函數和步驟。C&#xff1a;支持多范式&#xff0c;包括面向對象編程&#xff08;類、繼承、多態&…

Android LeakCanary 使用 · 原理詳解

一、簡介 LeakCanary 是 Square 公司開源的 Android 內存泄漏檢測工具&#xff0c;通過自動化監控和堆轉儲分析&#xff0c;幫助開發者快速定位內存泄漏根源。其核心設計輕量高效&#xff0c;已成為 Android 開發中必備的調試工具。 二、使用方式 1. 集成步驟 在項目的 buil…

每日一題---dd愛框框(Java中輸入數據過多)

dd愛框框 實例&#xff1a; 輸入&#xff1a; 10 20 1 1 6 10 9 3 3 5 3 7 輸出&#xff1a; 3 5 這道題要解決Java中輸入的數過多時&#xff0c;時間不足的的問題。 應用這個輸入模板即可解決&#xff1a; Java中輸入大量數據 import java.util.*; import java.io.*;pu…

redis部署架構

一、redis多實例部署 實例1 安裝目錄&#xff1a;/app/6380 數據目錄&#xff1a;/app/6380/data 實例2 安裝目錄&#xff1a;/app/6381 數據目錄&#xff1a;/app/6381/data 1、創建實例安裝目錄 2、拷貝實例的配置文件 3、編輯實例的配置文件 第…

vscode python相對路徑的問題

vscode python相對路徑的問題 最近使用使用vscode連接wsl2寫python時&#xff0c;經常遇到找不到包中的方法的問題&#xff0c;最終發現vscode在執行python代碼時目錄不是從當前python文件開始算起&#xff0c;而是從當前工作區的目錄開始算起&#xff0c;比如說我打開的是/ho…

面試vue2開發時怎么加載編譯速度(webpack)

可以輸入命令獲取默認 webpack 設置 vue inspect > set.js 1.使用緩存 configureWebpack: {cache: {type: filesystem, // 使用文件系統緩存類型buildDependencies: {config: [__filename] // 緩存依賴&#xff0c;例如webpack配置文件路徑}}}, 2.啟用 vue-loader (測試明…

uv命令介紹(高性能Python包管理工具,旨在替代pip、pip-tools和virtualenv等傳統工具)

文章目錄 **主要功能**1. **快速安裝和管理 Python 包**2. **生成和管理鎖文件 (requirements.lock)**3. **創建虛擬環境**4. **與 poetry 兼容** **核心優勢**1. **極快的速度**&#xff1a;基于 Rust 實現&#xff0c;利用多線程和緩存大幅加速依賴解析。2. **輕量且獨立**&a…

企業數據管理的成本與效率革命

在數字經濟時代&#xff0c;企業每天產生的數據量正以指數級速度增長。IDC預測&#xff0c;到2025年全球數據總量將突破180 ZB。面對海量數據存儲需求和有限的IT預算&#xff0c;企業逐漸意識到&#xff1a;將每字節數據都存儲在昂貴的高性能存儲設備上&#xff0c;既不經濟也不…

深度學習-服務器訓練SparseDrive過程記錄

1、cuda安裝 1.1 卸載安裝失敗的cuda 參考&#xff1a;https://blog.csdn.net/weixin_40826634/article/details/127493809 注意&#xff1a;因為/usr/local/cuda-xx.x/bin/下沒有卸載腳本&#xff0c;很可能是apt安裝的&#xff0c;所以通過執行下面的命令刪除&#xff1a; a…

洛谷每日1題-------Day20__P1401 [入門賽 #18] 禁止在 int 乘 int 時不開 long long

題目描述 在比賽中&#xff0c;根據數據范圍&#xff0c;分析清楚變量的取值范圍&#xff0c;是非常重要的。int 類型變量與 int 類型變量相乘&#xff0c;往往可能超出 int 類型可以表示的取值范圍。 現在&#xff0c;給出兩個 int 類型變量 x,y 及其取值范圍&#xff0c;請…