JavaScript Map 实现的缓存机制核心在于控制访问:支持任意类型 key、Promise 防重复请求、TTL 过期校验、LRU/FIFO 容量限制,轻量可控,适用于前端接口优化。

用 JavaScript 的 Map 设计自定义缓存机制,核心不是“存数据”,而是“控访问”——控制何时存、按什么存、什么时候删、并发时怎么防重复请求。它轻量、可控、不依赖外部库,特别适合前端接口级缓存优化。
用 Map 做缓存容器,比对象更合适
Map 天然支持任意类型作为 key(比如 URL + 参数对象),保留插入顺序,自带 has()、get()、delete() 和 size,写起来干净,逻辑也更可靠。普通对象只能用字符串当 key,遇到对象参数就得 JSON.stringify,容易出错;而 Map 可以直接拿配置对象、函数甚至 Symbol 当 key,更贴近真实使用场景。
- 键推荐用唯一可序列化字符串:如
url + '?' + new URLSearchParams(params).toString() - 避免直接用响应式对象或 Date 实例作 key(每次 new 都不同),应先提取关键字段再拼接
- 缓存值建议存完整响应体(如
res.data或整个res),方便后续统一处理状态码、错误等
支持并发:Promise 缓存防重复请求
多个相同请求同时触发时,只发一次网络请求,其余等待并复用结果——这是提升接口体验的关键一环。靠的是把正在 pending 的 Promise 本身存进 Map。
- 请求发起前,先查缓存:若命中已 resolve 的值,直接返回;若命中 pending 的 Promise,直接
await它 - 若未命中,发起请求,把新 Promise 存入 Map,请求完成后更新缓存值,并
resolve所有等待者 - 失败时也要
catch并从 Map 中清除该 key,避免下次永远卡在失败态
加有效期:TTL 控制自动过期
纯内存缓存不会自己“过期”,需要手动加时间维度。简单做法是缓存值包装成带时间戳的对象:
- 存的时候记下
timestamp: Date.now()和maxAge: 60_000(1 分钟) - 取的时候判断
Date.now() - item.timestamp > item.maxAge,超时则删除并重新请求 - 不建议用
setTimeout主动清理(内存泄漏风险高),按需校验更稳妥
限容量:LRU 或 FIFO 防止无限膨胀
尤其在列表页、搜索页等动态 key 场景,缓存可能越积越多。可以给 Map 加个最大长度约束:
- LRU 方式:每次 get/set 都把对应 key 移到末尾,size 超限时删掉第一个(最久未用)
- FIFO 方式:简单记录插入顺序,超限时删最早插入的项
- Vue/React 组件内使用时,可在
onUnmounted或useEffect cleanup中调用cache.clear()释放局部缓存











