如何实现一个前端缓存存取功能,我用js尝试实现了一个通用版本

大叫好,我是斯文,我最近遇到一个刷新功能接口数据5min才更新一次所以重复点击获取到的数据都是一样的于是想实现一个页面接口数据缓存存取功能,简单的getCache、setCache就能拿到缓存数据去使用,以下是热乎的具体内容

前端缓存存取功能

功能概述

实现两个ES5兼容的JavaScript函数,用于管理前端缓存数据。这些函数将支持自定义存储上下文、多键值管理和强制日志输出功能。

核心功能
  1. 数据存储函数:接收键名、数据和缓存失效时间,可选择存储上下文。自动添加存储时间,检测键名冲突并输出警告日志。
  2. 数据读取函数:接收键名和存储上下文,读取缓存数据并检查是否失效,输出操作日志,失效时返回null
技术细节
  • 存储结构:每个缓存项以键值对形式存储,包含原始数据、存储时间和失效时间。
  • 存储上下文:支持自定义对象存储,默认使用window对象。
  • 日志输出:所有操作强制输出日志,包括存储成功、键名冲突警告、读取成功/失败等信息。
代码实现

以下是基于ES5标准实现的缓存管理函数:

/**
 * 存储数据到缓存
 * @param {Object} options - 包含缓存配置的对象
 * @param {string} options.key - 缓存键名(必需)
 * @param {*} options.data - 需要缓存的数据(必需)
 * @param {number} options.expire - 缓存失效时间(毫秒,必需)
 * @param {Object} [options.context=window] - 存储上下文对象
 */
function setCache(options) {
  // 提取参数并设置默认值
  var key = options.key;
  var data = options.data;
  var expire = options.expire;
  var context = options.context || window;
  
  // 验证必需参数
  if (!key) {
    console.error("[Cache] 存储失败:缺少键名");
    return;
  }
  
  if (data === undefined) {
    console.error("[Cache] 存储失败:缺少数据");
    return;
  }
  
  if (typeof expire !== 'number' || expire <= 0) {
    console.error("[Cache] 存储失败:失效时间必须为正整数(毫秒)");
    return;
  }
  
  // 检测键名冲突
  if (context[key] !== undefined) {
    console.warn("[Cache] 警告:键名 '" + key + "' 已存在,将覆盖原有缓存");
  }
  
  // 创建缓存对象
  var cacheItem = {
    data: data,
    storeTime: new Date().getTime(),
    expire: expire
  };
  
  // 存储到指定上下文
  context[key] = cacheItem;
  
  // 输出成功日志
  console.log("[Cache] 数据已存储,键名:", key);
  console.log("[Cache] 失效时间:", new Date(cacheItem.storeTime + cacheItem.expire).toLocaleString());
}

/**
 * 从缓存读取数据
 * @param {Object} options - 包含读取配置的对象
 * @param {string} options.key - 缓存键名(必需)
 * @param {Object} [options.context=window] - 存储上下文对象
 * @returns {*|null} - 缓存数据(未过期)或null(过期或不存在)
 */
function getCache(options) {
  // 提取参数并设置默认值
  var key = options.key;
  var context = options.context || window;
  
  // 验证必需参数
  if (!key) {
    console.error("[Cache] 读取失败:缺少键名");
    return null;
  }
  
  // 从上下文获取缓存数据
  var cacheItem = context[key];
  
  // 如果缓存不存在,输出日志并返回null
  if (!cacheItem) {
    console.log("[Cache] 未找到缓存,键名:", key);
    return null;
  }
  
  // 计算当前时间与存储时间的差值
  var currentTime = new Date().getTime();
  var timeDiff = currentTime - cacheItem.storeTime;
  
  // 检查缓存是否过期
  if (timeDiff > cacheItem.expire) {
    // 缓存已过期,清除缓存
    delete context[key];
    
    // 输出过期日志
    console.log("[Cache] 缓存已过期,键名:", key);
    console.log("[Cache] 过期时间:", new Date(cacheItem.storeTime + cacheItem.expire).toLocaleString());
    
    return null;
  }
  
  // 缓存未过期,输出成功日志并返回数据
  console.log("[Cache] 读取成功,键名:", key);
  console.log("[Cache] 剩余有效期:", (cacheItem.expire - timeDiff) / 1000, "秒");
  
  return cacheItem.data;
}
使用示例
// 示例上下文对象
var myCacheContext = {};

// 正常存储数据
setCache({
  key: "userInfo",
  data: { username: "john", age: 30 },
  expire: 1800000, // 30分钟
  context: myCacheContext
});

// 尝试使用相同键名存储
setCache({
  key: "userInfo",
  data: { username: "jane", age: 25 },
  expire: 3600000, // 1小时
  context: myCacheContext
});

// 读取缓存数据
var userData = getCache({
  key: "userInfo",
  context: myCacheContext
});

// 使用默认上下文(window)存储
setCache({
  key: "settings",
  data: { theme: "dark", notifications: true },
  expire: 86400000 // 24小时
});

// 读取默认上下文的缓存
var settings = getCache({
  key: "settings"
});
注意事项
  • 建议为每个项目或模块创建独立的上下文对象,避免全局变量污染。
  • 日志功能为强制开启,便于调试和监控缓存使用情况。
  • 若需持久化存储(如跨页面会话),建议结合localStoragesessionStorage使用。
  • 键名冲突检测仅针对同一上下文,不同上下文可使用相同键名。

还可不可以优化呢? 有,以下是对当前缓存库的优化建议,从功能增强、代码健壮性、性能优化和使用体验四个维度展开:

一、功能增强建议

1. 批量操作支持
  • 增加 setBatchgetBatch 方法,支持一次性操作多个键值对,提升效率。
// 示例:批量设置缓存
setBatch({
  context: myCacheContext,
  items: [
    { key: "user1", data: { id: 1 }, expire: 3600000 },
    { key: "user2", data: { id: 2 }, expire: 7200000 }
  ]
});
2. 缓存清理策略
  • 添加 clearExpired 方法自动清理所有过期缓存,避免内存占用。
  • 实现 clearAll 方法支持清空指定上下文的全部缓存。
3. 数据序列化
  • 增加 serializedeserialize 选项,支持自定义数据序列化方式(如JSON.stringify/parse),方便存储复杂对象。

二、代码健壮性优化

1. 类型校验增强
  • 使用 typeofinstanceof 对关键参数进行类型校验,如:
    if (typeof key !== 'string') {
      throw new Error("[Cache] 键名必须为字符串类型");
    }
    
2. 错误处理升级
  • 将部分 console.error 改为抛出错误(如缺少必填参数时),让调用者明确感知异常。
  • 为关键操作添加 try-catch 保护,如:
    try {
      context[key] = cacheItem;
    } catch (e) {
      console.error("[Cache] 存储失败:", e.message);
    }
    
3. 防御性编程
  • 避免直接操作全局 window 对象,可改为:
    var globalContext = (function() {
      return this || (typeof window !== 'undefined' ? window : {});
    })();
    

三、性能优化

1. 缓存预热机制
  • 支持预加载常用缓存项,减少首次读取延迟:
    // 初始化时批量加载
    preloadCache(["userInfo", "settings"], myCacheContext);
    
2. LRU缓存淘汰策略
  • 对缓存数量设置上限,当超过限制时自动删除最久未使用的缓存项(需额外维护访问顺序)。

四、使用体验优化

1. 时间单位简化
  • 支持更友好的时间单位,如:
    // 支持 '10m'(10分钟)、'2h'(2小时)等格式
    setCache({ key: "data", expire: "1d", data: {... } });
    
  • 实现辅助函数:
    function parseTime(timeStr) {
      // 解析 '10m' 为 600000 毫秒
    }
    
2. 事件监听
  • 添加缓存变更事件,支持监听:
    onCacheChange("userInfo", function(newValue) {
      console.log("用户信息已更新");
    });
    
3. 增强日志
  • 支持日志级别控制:
    setLogLevel("debug"); // 可选:error/warn/info/debug
    

五、最终代码优化示例

以下是结合上述建议的优化代码片段(仅展示新增方法框架):

/**
 * 批量设置缓存
 * @param {Object} options - 配置对象
 * @param {Array} options.items - 缓存项数组 [{ key, data, expire }, ...]
 * @param {Object} [options.context=window] - 存储上下文
 */
function setBatch(options) {
  var items = options.items || [];
  var context = options.context || window;
  
  items.forEach(function(item) {
    setCache({
      key: item.key,
      data: item.data,
      expire: item.expire,
      context: context,
      // 内部调用不重复输出日志
      log: false
    });
  });
  
  console.log("[Cache] 批量设置完成,共", items.length, "项");
}

/**
 * 清理所有过期缓存
 * @param {Object} [context=window] - 存储上下文
 */
function clearExpired(context) {
  context = context || window;
  var currentTime = new Date().getTime();
  var clearedCount = 0;
  
  Object.keys(context).forEach(function(key) {
    var item = context[key];
    if (item && item.storeTime && item.expire) {
      if (currentTime - item.storeTime > item.expire) {
        delete context[key];
        clearedCount++;
      }
    }
  });
  
  console.log("[Cache] 清理完成,共删除", clearedCount, "个过期缓存");
}

六、文档补充建议

  1. 使用示例:增加复杂场景示例,如批量操作、跨页面缓存共享。
  2. API参考:完善每个方法的参数说明和返回值描述。
  3. 错误处理:明确说明可能抛出的错误类型及处理方式。
  4. 性能考量:提醒大对象存储对内存的影响,建议缓存数据轻量化。

这些优化可以让缓存库更健壮、灵活,同时保持ES5兼容性。是否需要进一步实现某个优化点,可根据实际项目需求决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员斯文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值