XHR / Fetch / Axios 请求的取消请求与请求重试

XHR / Fetch / Axios 请求的取消请求请求重试是前端性能优化与稳定性处理的重点,也是面试高频内容。下面是这三种方式的详解封装方案(可直接复用)。


✅ 一、Axios 取消请求与请求重试封装

1. 安装依赖(可选,用于扩展)

npm install axios

2. 封装 cancelToken 与 retry 的 axios 请求模块

// axiosRequest.js
import axios from 'axios'const pendingMap = new Map()// 生成唯一 key(用于标记请求)
function getRequestKey(config) {const { method, url, params, data } = configreturn [method, url, JSON.stringify(params), JSON.stringify(data)].join('&')
}// 添加请求到 pendingMap
function addPending(config) {const key = getRequestKey(config)config.cancelToken = new axios.CancelToken(cancel => {if (!pendingMap.has(key)) {pendingMap.set(key, cancel)}})
}// 移除请求
function removePending(config) {const key = getRequestKey(config)if (pendingMap.has(key)) {const cancel = pendingMap.get(key)cancel && cancel()pendingMap.delete(key)}
}// 重试机制封装
function retryAdapterEnhancer(adapter, options = {}) {const { retries = 3, delay = 1000 } = optionsreturn async config => {let retryCount = 0const request = async () => {try {return await adapter(config)} catch (err) {if (retryCount < retries) {retryCount++await new Promise(res => setTimeout(res, delay))return request()} else {return Promise.reject(err)}}}return request()}
}// 创建实例
const axiosInstance = axios.create({timeout: 5000,adapter: retryAdapterEnhancer(axios.defaults.adapter, { retries: 2, delay: 1000 })
})// 请求拦截器
axiosInstance.interceptors.request.use(config => {removePending(config)addPending(config)return config
})// 响应拦截器
axiosInstance.interceptors.response.use(response => {removePending(response.config)return response},error => {if (axios.isCancel(error)) {console.warn('Request canceled:', error.message)}return Promise.reject(error)}
)export default axiosInstance

✅ 使用示例:

import request from './axiosRequest'request.get('/api/data', { params: { id: 1 } }).then(res => console.log(res)).catch(err => console.error(err))

✅ 二、Fetch 封装(支持取消请求 & 重试)

1. 使用 AbortController 封装取消与重试

// fetchRequest.js
export function fetchWithRetry(url, options = {}, retries = 3, delay = 1000) {const controller = new AbortController()options.signal = controller.signalconst fetchData = (retryCount = 0) => {return fetch(url, options).then(res => {if (!res.ok) throw new Error('Network response was not ok')return res}).catch(err => {if (retryCount < retries && err.name !== 'AbortError') {return new Promise(resolve =>setTimeout(() => resolve(fetchData(retryCount + 1)), delay))}throw err})}return {promise: fetchData(),cancel: () => controller.abort()}
}

✅ 使用示例:

const { promise, cancel } = fetchWithRetry('/api/data', {}, 2, 1000)promise.then(res => res.json()).then(data => console.log(data)).catch(err => console.error(err))// 调用 cancel() 可随时取消请求

✅ 三、XHR 原生封装(带取消 & 重试)

// xhrRequest.js
export function xhrWithRetry({ url, method = 'GET', data = null, retries = 3, delay = 1000 }) {let xhr = nullconst send = (retryCount = 0, resolve, reject) => {xhr = new XMLHttpRequest()xhr.open(method, url, true)xhr.onreadystatechange = () => {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {resolve(xhr.responseText)} else if (retryCount < retries) {setTimeout(() => send(retryCount + 1, resolve, reject), delay)} else {reject(new Error(`Request failed: ${xhr.status}`))}}}xhr.onerror = () => reject(new Error('Network Error'))xhr.send(data)}const promise = new Promise((resolve, reject) => send(0, resolve, reject))return {promise,cancel: () => xhr && xhr.abort()}
}

✅ 使用示例:

const { promise, cancel } = xhrWithRetry({ url: '/api/data' })promise.then(res => console.log(res)).catch(err => console.error(err))// 可随时调用取消
cancel()

✅ 总结对比

特性/方式取消支持重试支持易用性推荐场景
Axios✔️ CancelToken✔️ 自定义 adapter✅ 最佳Vue/React 项目
Fetch✔️ AbortController✔️ 手动封装✅ 清晰原生 / SSR 项目
XHR✔️ abort()✔️ 手动封装❌ 复杂老旧兼容需求

如果你想把这三套方案整合成一个通用库或 TypeScript 模块,我也可以帮你封装成统一接口版本。是否需要我继续处理这部分?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/83928.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025最新Java日志框架深度解析:Log4j 2 vs Logback性能实测+企业级实战案例

一、为什么printStackTrace是"代码坟场"&#xff1f; 你写的日志可能正在拖垮系统&#xff01; 在Java开发中&#xff0c;直接调用printStackTrace()打印异常堆栈是最常见的"自杀式操作"。这种方式会导致三大致命问题&#xff1a; 无法分级控制&#xff…

前端面试四之Fetch API同步和异步

Fetch API&#xff08;Fetch Application Programming Interface&#xff09;是一个现代的、基于Promise的网络请求接口&#xff0c;用于在浏览器环境中发起网络请求并处理响应。它是对传统XMLHttpRequest的改进&#xff0c;提供了更简洁、灵活和强大的功能&#xff0c;广泛应用…

ubuntu 20.04挂载固态硬盘

我们有个工控机&#xff0c;其操作系统是ubuntu 20.04。可以接入一个固态硬盘。将固态硬盘插好后&#xff0c;就要进行挂载。在AI的指导下&#xff0c;过程并不顺利。记录如下&#xff1a; 1、检查硬盘是否被识别 安装好硬盘后&#xff0c;运行以下命令来检查Linux系统是否…

涂装协作机器人:重新定义涂装工艺的智能化未来

一、涂装场景的产业变革与核心诉求 1.1 千亿级市场的技术突围战 在汽车制造领域&#xff0c;涂装车间被称为"工业化妆间"&#xff0c;其工艺质量直接影响产品溢价能力。当前行业面临三重挑战&#xff1a; 质量维度&#xff1a;传统人工喷涂存在膜厚波动15μm的行业…

Unity优化篇之DrawCall

当然可以&#xff01;以下是完整、详尽、可发布的博客文章&#xff0c;专注讲解 Unity 的静态合批与动态合批机制&#xff0c;并详细列出它们对 Shader 的要求和所有限制条件。文章结构清晰、技术深度足够&#xff0c;适合发布在 CSDN、掘金、知乎等技术平台。 urp默认隐藏动态…

Electron桌面应用下,在拍照、展示pdf等模块时,容易导致应用白屏

Electron 应用白屏问题分析与解决方案 Electron 应用中拍照、PDF展示等模块导致白屏的常见原因通常与内存泄漏、渲染进程崩溃或资源加载超时有关。以下是具体排查与解决方法&#xff1a; 检查内存泄漏 项目中&#xff0c;分析代码&#xff0c;高频操作或未释放的资源可能导致…

比对++Hex or Bin文件

用NotePad 安装 ​​ Hex-Editor 插件 1.1参考方法路径https://cloud.tencent.com/developer/article/2311013 1.2 下载 Hex-Editor.dll文件路劲 https://sourceforge.net/projects/npp-plugins/ 比对 2.1, 显示Bin 插件/Hex Editor/View in Hex 2.2 插件/Compare(运行很不流…

以STM32H7微控制器为例,简要说明stm32h7xx_it.c的作用

在STM32开发中&#xff0c;stm32h7xx_it.c文件是中断服务例程&#xff08;ISR, Interrupt Service Routine&#xff09;的核心实现文件&#xff0c;其作用与产生的逻辑如下&#xff1a; 一、文件的核心作用 中断处理入口 该文件定义了STM32H7微控制器所有硬件中断和异常的处理函…

若依框架页面缓存查询条件后,切换页面想重新请求一下数据

因为框架使用了Keep-Alive缓存组件&#xff0c;所以使用onActivated钩子 import { onActivated } from vue;// 当组件从缓存中重新激活时 onActivated(() > {getList(); });

智能心理医疗助手开发实践:从技术架构到人文关怀——CangjieMagic情感医疗应用技术实践

作为一名长期耕耘在医疗健康领域的技术开发者&#xff0c;我至今仍清晰地记得三年前那个深夜——当我调试的心理健康AI第一次对用户的情绪崩溃做出恰当回应时&#xff0c;整个团队爆发的欢呼声。那一刻&#xff0c;我深刻意识到技术不只是冰冷的逻辑&#xff0c;更可以成为温暖…

汉诺塔问题深度解析

汉诺塔问题深度解析 一、汉诺塔问题的起源与背景1.1 问题起源1.2 历史发展 二、汉诺塔问题的描述与规则2.1 问题描述2.2 示例说明 三、汉诺塔问题的递归求解原理3.1 递归思想概述3.2 汉诺塔问题的递归分解3.3 递归调用栈分析 四、汉诺塔问题的多语言实现4.1 Python实现4.2 C实现…

【Node.js 深度解析】npm install 遭遇:npm ERR! code CERT_HAS_EXPIRED 错误的终极解决方案

目录 &#x1f4da; 目录&#xff1a;洞悉症结&#xff0c;精准施治 &#x1f50d; 一、精准剖析&#xff1a;CERT_HAS_EXPIRED 的本质 &#x1f575;️ 二、深度溯源&#xff1a;证书失效的 N 重诱因 &#x1f4a1; 三、高效解决策略&#xff1a;六脉神剑&#xff0c;招招…

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…

Double/Debiased Machine Learning

独立同步分布的观测数据 { W i ( Y i , D i , X i ) ∣ i ∈ { 1 , . . . , n } } \{W_i(Y_i,D_i,X_i)| i\in \{1,...,n\}\} {Wi​(Yi​,Di​,Xi​)∣i∈{1,...,n}}&#xff0c;其中 Y i Y_i Yi​表示结果变量&#xff0c; D i D_i Di​表示因变量&#xff0c; X i X_i Xi​表…

Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(八):异步处理逻辑详解

在现代 Web 应用中&#xff0c;异步处理是实现流畅交互的核心技术。本文基于前几章实现的内容Tailwind CSS 实战&#xff1a;基于 Kooboo 构建 AI 对话框页面&#xff08;七&#xff09;&#xff1a;消息框交互功能添加-CSDN博客&#xff0c;深入解析 AI 对话框页面中异步逻辑的…

Asp.net Core 通过依赖注入的方式获取用户

思路&#xff1a;Web项目中&#xff0c;需要根据当前登陆的用户&#xff0c;查询当前用户所属的数据、添加并标识对象等。根据请求头Authorization 中token&#xff0c;获取Redis中存储的用户对象。 本做法需要完成 基于StackExchange.Redis 配置&#xff0c;参考&#xff1a;…

Vue3 + UniApp 蓝牙连接与数据发送(稳定版)

本教程适用于使用 uni-app Vue3 (script setup) 开发的跨平台 App&#xff08;支持微信小程序、H5、Android/iOS 等&#xff09; &#x1f3af; 功能目标 ✅ 获取蓝牙权限✅ 扫描周围蓝牙设备✅ 连接指定蓝牙设备✅ 获取服务和特征值✅ 向设备发送数据包&#xff08;ArrayBu…

Docker + Nginx + Logrotate 日志管理与轮换实践

概述与背景 Docker 容器化环境中 Nginx 日志管理的挑战Logrotate 的作用与必要性结合场景的实际需求&#xff08;如日志切割、压缩、归档&#xff09; Docker 环境下的 Nginx 日志配置 Nginx 日志路径与 Docker 数据卷映射 volumes:- ./nginx/logs:/var/log/nginxLogrotate …

涂胶协作机器人解决方案 | Kinova Link 6 Cobot在涂胶工业的方案应用与价值

涂胶工业现状背景&#xff1a; 涂胶工艺在汽车制造、电子组装、航空航天等工业领域极为关键&#xff0c;关乎产品密封、防水、绝缘性能及外观质量。 然而&#xff0c;传统涂胶作业问题频发。人工操作重复性强易疲劳&#xff0c;涂胶质量波动大&#xff1b;大型涂胶器使用增加工…