如何利用高阶函数实现的请求缓存层减少对后端冗余数据的二次查询

作者:袖梨 2026-06-08
高阶函数实现请求缓存层,通过闭包维护基于 JSON.stringify(args) 的键值缓存对象,支持异步、TTL 过期、force 强制刷新及仅 GET 缓存;示例 cachedFetch 封装 fetchFn,返回带记忆能力的 Promise 函数。

用高阶函数实现请求缓存层,核心是把“发请求”这个动作封装成可记忆、可复用的函数,避免相同参数反复调用后端。它不依赖框架或第三方库,靠闭包维持缓存状态,轻量且可控。

缓存函数的基本结构

高阶函数接收原始请求函数,返回一个带记忆能力的新函数:

  • 内部维护一个普通对象(不能用 Map,因为对象/数组参数用 === 比较会失败)
  • JSON.stringify(args) 把参数转为唯一字符串 key
  • 命中缓存就直接返回;未命中则执行原函数,并把结果存入缓存再返回

适配真实请求场景的关键调整

纯计算缓存(如 add(2))和请求缓存有本质区别:HTTP 请求可能失败、需支持过期、要兼容 Promise。所以实际封装时需补充:

  • 支持异步:返回 Promise,缓存值也存 Promise 实例(避免并发重复请求)
  • 设置 TTL:每个缓存项记录时间戳,读取前校验是否过期
  • 允许强制刷新:比如加个 force: true 参数跳过缓存
  • 区分 GET 与非 GET:只对幂等请求(如 GET)启用缓存,POST/PUT 不缓存

一个可用的请求缓存高阶函数示例

下面是一个生产环境可用的简化版:

const cachedFetch = (fetchFn, ttl = 5000) => {  const cache = {}  return async (...args) => {    const key = JSON.stringify(args)    const now = Date.now()<pre class='brush:php;toolbar:false;'>if (cache[key]) {  const { data, timestamp } = cache[key]  if (now - timestamp < ttl) return data}try {  const data = await fetchFn(...args)  cache[key] = { data, timestamp: now }  return data} catch (err) {  // 缓存失败时不写入,避免脏数据  throw err}

}}

// 使用方式const apiGetUser = (id) => fetch(/api/user/${id}).then(r => r.json())const cachedGetUser = cachedFetch(apiGetUser, 10000)

cachedGetUser(123) // 首次请求,走网络cachedGetUser(123) // 10 秒内再次调用,直接返回缓存结果

和前端框架缓存的配合建议

高阶函数缓存适合做「请求粒度」控制,但不宜替代整体数据流管理:

  • 在 React 中,可结合 useMemo 或自定义 Hook 封装,避免组件重渲染时重复初始化缓存函数
  • 与 Redux / Zustand 配合时,缓存层放在 API 调用入口,状态管理层只负责消费数据,职责分离
  • 注意清理时机:比如用户登出、关键数据变更后,应手动清空相关 key 的缓存

相关文章

精彩推荐