找回密码
 立即注册
首页 业界区 业界 JavaScript 实现支持过期时间的数据缓存功能 ...

JavaScript 实现支持过期时间的数据缓存功能

僚娥 2025-6-6 10:12:19
JavaScript 实现支持过期时间的数据缓存功能

要在 JavaScript 中实现数据缓存功能并支持设置过期时间,可以使用 localStorage、sessionStorage 或内存对象(如 Map 或普通对象)来存储数据,并为每个缓存项设置一个过期时间。以下是一个简单的实现示例:
JavaScript 实现支持过期时间的数据缓存功能

1. 使用 localStorage 实现持久缓存
  1. const Cache = {
  2.   /**
  3.    * 设置缓存
  4.    * @param {string} key - 缓存键
  5.    * @param {*} value - 缓存值
  6.    * @param {number} ttl - 缓存时间(毫秒)
  7.    */
  8.   set(key, value, ttl) {
  9.     const data = {
  10.       value,
  11.       expiry: ttl ? Date.now() + ttl : null, // 计算过期时间
  12.     };
  13.     localStorage.setItem(key, JSON.stringify(data));
  14.   },
  15.   /**
  16.    * 获取缓存
  17.    * @param {string} key - 缓存键
  18.    * @returns {*} 缓存值或 null(如果过期或不存在)
  19.    */
  20.   get(key) {
  21.     const data = localStorage.getItem(key);
  22.     if (!data) return null;
  23.     try {
  24.       const { value, expiry } = JSON.parse(data);
  25.       if (expiry && Date.now() > expiry) {
  26.         localStorage.removeItem(key); // 过期删除缓存
  27.         return null;
  28.       }
  29.       return value;
  30.     } catch (e) {
  31.       console.warn("缓存数据解析失败", e);
  32.       return null;
  33.     }
  34.   },
  35.   /**
  36.    * 删除缓存
  37.    * @param {string} key - 缓存键
  38.    */
  39.   remove(key) {
  40.     localStorage.removeItem(key);
  41.   },
  42.   /**
  43.    * 清空所有缓存
  44.    */
  45.   clear() {
  46.     localStorage.clear();
  47.   },
  48. };
  49. // 使用示例
  50. Cache.set("username", "Alice", 5000); // 设置缓存5秒后过期
  51. console.log(Cache.get("username")); // 5秒内返回 'Alice'
  52. setTimeout(() => console.log(Cache.get("username")), 6000); // 6秒后返回 null
复制代码
⚠️ 注意事项

  • localStorage 只能存储字符串,因此要使用 JSON.stringify 和 JSON.parse 进行序列化和反序列化。
  • localStorage 的存储空间一般有限(大约 5MB)。
  • 如果是跨页面使用,请确保在相同的域名下。
2. 使用 sessionStorage 实现数据缓存(适合页面级临时存储)

sessionStorage 是一种浏览器存储机制,它的特点是数据仅在页面会话(session) 期间有效,页面关闭后数据会被清除。
  1. const SessionCache = {
  2.   /**
  3.    * 设置缓存
  4.    * @param {string} key - 缓存键
  5.    * @param {*} value - 缓存值
  6.    * @param {number} ttl - 缓存时间(毫秒)
  7.    */
  8.   set(key, value, ttl) {
  9.     const data = {
  10.       value,
  11.       expiry: ttl ? Date.now() + ttl : null, // 计算过期时间
  12.     };
  13.     sessionStorage.setItem(key, JSON.stringify(data));
  14.   },
  15.   /**
  16.    * 获取缓存
  17.    * @param {string} key - 缓存键
  18.    * @returns {*} 缓存值或 null(如果过期或不存在)
  19.    */
  20.   get(key) {
  21.     const data = sessionStorage.getItem(key);
  22.     if (!data) return null;
  23.     try {
  24.       const { value, expiry } = JSON.parse(data);
  25.       if (expiry && Date.now() > expiry) {
  26.         sessionStorage.removeItem(key); // 缓存已过期,删除
  27.         return null;
  28.       }
  29.       return value;
  30.     } catch (e) {
  31.       console.warn("缓存数据解析失败:", e);
  32.       return null;
  33.     }
  34.   },
  35.   /**
  36.    * 删除缓存
  37.    * @param {string} key - 缓存键
  38.    */
  39.   remove(key) {
  40.     sessionStorage.removeItem(key);
  41.   },
  42.   /**
  43.    * 清空所有缓存
  44.    */
  45.   clear() {
  46.     sessionStorage.clear();
  47.   },
  48. };
  49. // **使用示例**
  50. // 设置缓存,5秒后过期
  51. SessionCache.set("userToken", "abc123", 5000);
  52. // 获取缓存
  53. console.log(SessionCache.get("userToken")); // 5秒内返回 'abc123'
  54. // 5秒后尝试获取缓存
  55. setTimeout(() => {
  56.   console.log(SessionCache.get("userToken")); // 返回 null
  57. }, 6000);
复制代码
⚠️ 注意事项

  • sessionStorage 数据在页面关闭或会话结束时自动清除。
  • 在不同的标签页中,sessionStorage 是独立的(不会共享)。
  • sessionStorage 的存储空间一般为5MB左右。
  • 数据存储在 sessionStorage 时必须经过 JSON.stringify 和 JSON.parse 处理。
3. 使用内存对象实现轻量缓存(适合短期缓存)
  1. class MemoryCache {
  2.   constructor() {
  3.     this.cache = new Map();
  4.   }
  5.   /**
  6.    * 设置缓存
  7.    * @param {string} key - 缓存键
  8.    * @param {*} value - 缓存值
  9.    * @param {number} ttl - 缓存时间(毫秒)
  10.    */
  11.   set(key, value, ttl) {
  12.     const expiry = ttl ? Date.now() + ttl : null;
  13.     this.cache.set(key, { value, expiry });
  14.   }
  15.   /**
  16.    * 获取缓存
  17.    * @param {string} key - 缓存键
  18.    * @returns {*} 缓存值或 null(如果过期或不存在)
  19.    */
  20.   get(key) {
  21.     const item = this.cache.get(key);
  22.     if (!item) return null;
  23.     if (item.expiry && Date.now() > item.expiry) {
  24.       this.cache.delete(key); // 缓存过期,删除
  25.       return null;
  26.     }
  27.     return item.value;
  28.   }
  29.   /**
  30.    * 删除缓存
  31.    * @param {string} key - 缓存键
  32.    */
  33.   remove(key) {
  34.     this.cache.delete(key);
  35.   }
  36.   /**
  37.    * 清空所有缓存
  38.    */
  39.   clear() {
  40.     this.cache.clear();
  41.   }
  42. }
  43. // 使用示例
  44. const memCache = new MemoryCache();
  45. memCache.set("token", "abc123", 3000); // 设置缓存3秒后过期
  46. console.log(memCache.get("token")); // 3秒内返回 'abc123'
  47. setTimeout(() => console.log(memCache.get("token")), 4000); // 4秒后返回 null
复制代码
4. 使用 IndexedDB 实现持久缓存(支持二进制数据)
  1. // 初始化 IndexedDB 数据库
  2. class IndexedDBCache {
  3.   constructor(dbName = "CacheDB", storeName = "CacheStore") {
  4.     this.dbName = dbName;
  5.     this.storeName = storeName;
  6.     this.db = null;
  7.   }
  8.   /**
  9.    * 初始化数据库
  10.    */
  11.   async init() {
  12.     return new Promise((resolve, reject) => {
  13.       const request = indexedDB.open(this.dbName, 1);
  14.       request.onupgradeneeded = (event) => {
  15.         const db = event.target.result;
  16.         if (!db.objectStoreNames.contains(this.storeName)) {
  17.           db.createObjectStore(this.storeName, { keyPath: "key" });
  18.         }
  19.       };
  20.       request.onsuccess = (event) => {
  21.         this.db = event.target.result;
  22.         resolve(this);
  23.       };
  24.       request.onerror = (event) => {
  25.         console.error("IndexedDB 初始化失败:", event.target.error);
  26.         reject(event.target.error);
  27.       };
  28.     });
  29.   }
  30.   /**
  31.    * 获取对象存储
  32.    */
  33.   getObjectStore(mode = "readonly") {
  34.     const transaction = this.db.transaction(this.storeName, mode);
  35.     return transaction.objectStore(this.storeName);
  36.   }
  37.   /**
  38.    * 添加或更新缓存
  39.    * @param {string} key - 缓存键
  40.    * @param {*} value - 缓存值
  41.    * @param {number} ttl - 过期时间(毫秒)
  42.    */
  43.   async set(key, value, ttl) {
  44.     const expiry = ttl ? Date.now() + ttl : null;
  45.     const record = { key, value, expiry };
  46.     return new Promise((resolve, reject) => {
  47.       const store = this.getObjectStore("readwrite");
  48.       const request = store.put(record);
  49.       request.onsuccess = () => resolve(true);
  50.       request.onerror = (event) => {
  51.         console.error("数据写入失败:", event.target.error);
  52.         reject(event.target.error);
  53.       };
  54.     });
  55.   }
  56.   /**
  57.    * 获取缓存
  58.    * @param {string} key - 缓存键
  59.    * @returns {*} 缓存值或 null
  60.    */
  61.   async get(key) {
  62.     return new Promise((resolve, reject) => {
  63.       const store = this.getObjectStore("readonly");
  64.       const request = store.get(key);
  65.       request.onsuccess = (event) => {
  66.         const record = event.target.result;
  67.         if (!record) {
  68.           resolve(null); // 数据不存在
  69.           return;
  70.         }
  71.         if (record.expiry && Date.now() > record.expiry) {
  72.           // 数据过期
  73.           this.delete(key).then(() => resolve(null));
  74.         } else {
  75.           resolve(record.value); // 返回未过期数据
  76.         }
  77.       };
  78.       request.onerror = (event) => {
  79.         console.error("数据读取失败:", event.target.error);
  80.         reject(event.target.error);
  81.       };
  82.     });
  83.   }
  84.   /**
  85.    * 删除缓存
  86.    * @param {string} key - 缓存键
  87.    */
  88.   async delete(key) {
  89.     return new Promise((resolve, reject) => {
  90.       const store = this.getObjectStore("readwrite");
  91.       const request = store.delete(key);
  92.       request.onsuccess = () => resolve(true);
  93.       request.onerror = (event) => {
  94.         console.error("数据删除失败:", event.target.error);
  95.         reject(event.target.error);
  96.       };
  97.     });
  98.   }
  99.   /**
  100.    * 清空缓存
  101.    */
  102.   async clear() {
  103.     return new Promise((resolve, reject) => {
  104.       const store = this.getObjectStore("readwrite");
  105.       const request = store.clear();
  106.       request.onsuccess = () => resolve(true);
  107.       request.onerror = (event) => {
  108.         console.error("缓存清空失败:", event.target.error);
  109.         reject(event.target.error);
  110.       };
  111.     });
  112.   }
  113. }
  114. // 使用示例
  115. (async () => {
  116.   // 创建缓存实例并初始化数据库
  117.   const cache = new IndexedDBCache();
  118.   await cache.init();
  119.   // 设置缓存,数据 5 秒后过期
  120.   await cache.set("userToken", "abc123", 5000);
  121.   console.log("缓存设置完成");
  122.   // 缓存二进制数据
  123.   const binaryData = new Blob(["Hello, IndexedDB"], { type: "text/plain" });
  124.   await cache.set("binary", binaryData, 5000);
  125.   // 获取缓存
  126.   console.log("立即获取:", await cache.get("userToken")); // 输出: abc123
  127.   console.log("立即获取:", await cache.get("binary"));
  128.   // 等待 6 秒后尝试获取缓存
  129.   setTimeout(async () => {
  130.     console.log("6 秒后获取:", await cache.get("userToken")); // 输出: null
  131.     console.log("6 秒后获取:", await cache.get("binary")); // 输出: null
  132.   }, 6000);
  133. })();
复制代码

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册