【26-请求缓存】js实现一个请求缓存的功能-bysking

功能总结

BcRequestCacheStore 类实现了一个基于内存的请求缓存机制,主要用于避免重复请求、减少接口调用次数以及提高性能。以下是其主要功能点: 缓存管理

  • 使用 Map 数据结构存储缓存数据 (cache) 和正在执行的请求 (bcRequestCache)。
  • 每个缓存项包含 value(缓存值)和 expiry(过期时间),支持 TTL(Time To Live)机制。

请求去重 : - 如果多个并行请求具有相同的 key,只会发送一次实际请求,其余请求会等待该请求完成并返回结果,避免重复调用接口。

缓存命中与过期检查 : - 在发起请求前,先检查缓存中是否存在对应 key 的数据。 - 如果缓存未过期,则直接返回缓存值;如果已过期,则清理缓存并重新发起请求。

错误处理: - 如果请求失败,会捕获错误并抛出异常,同时不会污染缓存。

缓存清除 : - 提供 clear 方法,用于清空所有缓存数据。

实例化 : - 通过 export const cacheRegStore = new BcRequestCacheStore(5000); 创建了一个全局缓存实例,TTL 设置为 5 秒。

使用示例

  • 调用 cacheRegStore.request 方法时,传入一个唯一标识 key 和一个异步请求函数 requestFn
  • 示例中,key 是动态生成的字符串(如 uniq_id_${id}),requestFn 是调用 apiFromServer 的异步函数。

核心逻辑

缓存优先:优先从缓存中获取数据,减少不必要的网络请求。

并发控制 :通过 bcRequestCache 管理正在执行的请求,避免重复调用。

生命周期管理:缓存有明确的过期时间,确保数据的新鲜度。

适用场景 适用于需要频繁调用相同接口且结果在一定时间内不会变化的场景,例如:

  • 数据查询接口(如用户信息、配置信息等)。
  • 需要限制请求频率的场景。
js 复制代码
class BcRequestCacheStore {
  cache; // 存放请求的函数,结果
  ttl; // 缓存过期时间
  bcRequestCache: Map<string, Promise<unknown> | null>; // 存放请求的函数,避免同时发送相同请求
  constructor(ttl = 60000) {
    this.cache = new Map();
    this.bcRequestCache = new Map();
    this.ttl = ttl;
  }

  async request(
    key: string,
    requestFn: (...args: unknown[]) => Promise<unknown>,
  ) {
    // 检查缓存值
    if (this.cache.has(key)) {
      const { value, expiry } = this.cache.get(key);

      // 缓存过期时间检查
      if (expiry > Date.now()) {
        return value;
      }

      // 缓存过期清理
      this.cache.delete(key);
    }

    // 判断是否正在执行,是的话就等待, 处理并行请求相同请求的场景,如果已经有一个相同请求真正发送,直接等待它即可,不需要重新创建
    if (this.bcRequestCache.get(key)) {
      return this.bcRequestCache.get(key);
    }

    try {
      // 发送一个新请求,并加入缓存集合
      this.bcRequestCache.set(key, requestFn());

      // 获取请求成功的值并加入缓存
      const value = await this.bcRequestCache.get(key);
      this.cache.set(key, {
        value,
        expiry: Date.now() + this.ttl,
      });

      // 请求完成后讲请求缓存集合设置空
      this.bcRequestCache.set(key, null);
      return value;
    } catch (error) {
      console.error('Request failed:', error);
      throw error;
    }
  }

  clear() {
    this.cache.clear();
  }
}

/** 接口缓存实例*/
export const cacheRegStore = new BcRequestCacheStore(5000);

const res = await cacheRegStore.request(`uniq_id_${id}`, async () => {
  let resData = await apiFromServer({
    id,
  });

  return resData;
});
相关推荐
前端程序猿i2 分钟前
Vue组件库开发实战:从0到1构建可复用的微前端模块
前端·javascript·vue.js
幼儿园技术家9 分钟前
微信小程序/H5 调起确认收款界面
前端
键指江湖9 分钟前
React 对state进行保留和重置
javascript·react.js·ecmascript
微笑边缘的金元宝14 分钟前
Echarts柱状图斜线环纹(图形的贴花图案)
前端·javascript·echarts
wuxiguala19 分钟前
【web考试系统的设计】
前端
独立开阀者_FwtCoder1 小时前
CSS view():JavaScript 滚动动画的终结
前端·javascript·vue.js
咖啡教室1 小时前
用markdown语法制作一个好看的网址导航页面(markdown-web-nav)
前端·javascript·markdown
独立开阀者_FwtCoder2 小时前
Vue 团队“王炸”新作!又一打包工具发布!
前端·javascript·vue.js
天天扭码2 小时前
一分钟解决“3.无重复字符的最长字串问题”(最优解)
前端·javascript·算法
独立开阀者_FwtCoder2 小时前
Promise 引入全新 API!效率提升 300%!
前端·javascript·后端