axios请求缓存与重复拦截:“相同请求未完成时,不发起新请求”

javascript 复制代码
import axios from "axios";

// 1. 缓存已完成的请求结果(key:请求URL+参数,value:数据)
const requestCache = new Map();
// 2. 记录正在执行的请求(避免并行重复请求)
const pendingRequests = new Set();

// 请求拦截器:发起请求前检查
axios.interceptors.request.use(config => {
  // 生成请求唯一标识(URL + 方法 + 参数)
  const requestKey = `${config.url}-${config.method}-${JSON.stringify(config.params)}`;

  // 情况1:请求正在执行中,拦截新请求
  if (pendingRequests.has(requestKey)) {
    return Promise.reject(new Error("当前请求已在执行,请勿重复触发"));
  }

  // 情况2:请求已缓存,直接返回缓存数据(不发新请求)
  if (requestCache.has(requestKey)) {
    return Promise.resolve({ data: requestCache.get(requestKey) });
  }

  // 情况3:新请求,加入"正在执行"列表
  pendingRequests.add(requestKey);
  return config;
});

// 响应拦截器:请求完成后更新缓存/状态
axios.interceptors.response.use(
  response => {
    const requestKey = `${response.config.url}-${response.config.method}-${JSON.stringify(response.config.params)}`;
    // 1. 缓存请求结果
    requestCache.set(requestKey, response.data);
    // 2. 从"正在执行"列表移除
    pendingRequests.delete(requestKey);
    return response;
  },
  error => {
    // 错误时也移除"正在执行"状态
    const requestKey = `${error.config.url}-${error.config.method}-${JSON.stringify(error.config.params)}`;
    pendingRequests.delete(requestKey);
    return Promise.reject(error);
  }
);

// 调用示例:相同参数的请求,短时间内只发一次
function fetchStyle() {
  axios.get("/api/page-style", { params: { theme: "light" } })
    .then(res => console.log("样式数据(缓存/新请求):", res.data))
    .catch(err => console.log("请求拦截:", err.message));
}

// 1秒内调用3次,只发1次请求,后2次用缓存
fetchStyle();
setTimeout(fetchStyle, 500);
setTimeout(fetchStyle, 800);

这个地方的set和map使用,为什么不用对象和数组?

  1. 用普通对象 {} 替代 Map:
    可行,但键只能是字符串 / Symbol,且判断键是否存在需要用 obj.hasOwnProperty(key)(不如 map.has(key) 直观)。
  2. 用数组 \[\] 替代 Set:
    可行,但检查是否存在需要 array.includes(key)(O (n) 复杂度,数据量大时效率低),且需要手动去重(if (!array.includes(key)) array.push(key))。
相关推荐
Joy T5 小时前
Spring AI 项目中的 pom.xml、application.yml 与 Nacos:从依赖管理到运行配置
spring·nacos·pom.xml·profile·参数配置·application.yml
Setsuna_F_Seiei6 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
志尊宝6 小时前
Vue3 零基础每日笔记(073):keep-alive 页面缓存实战——列表页返回不丢状态
vue.js·笔记·缓存·#vue #前端 #前端开发·#javascript·#vue.js
zhangzeyuaaa7 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
默_笙7 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯7 小时前
标签打印软件怎么对接 Excel 数据
前端·excel
禾小西7 小时前
Redis:从两大维度和三大主线建立知识体系
数据库·redis·缓存
一个风轻云淡8 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u0111026759 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说9 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic