JavaScript 实现支持过期时间的数据缓存功能
要在 JavaScript 中实现数据缓存功能并支持设置过期时间,可以使用 localStorage、sessionStorage 或内存对象(如 Map 或普通对象)来存储数据,并为每个缓存项设置一个过期时间。以下是一个简单的实现示例:
JavaScript 实现支持过期时间的数据缓存功能
1. 使用 localStorage 实现持久缓存
- const Cache = {
- /**
- * 设置缓存
- * @param {string} key - 缓存键
- * @param {*} value - 缓存值
- * @param {number} ttl - 缓存时间(毫秒)
- */
- set(key, value, ttl) {
- const data = {
- value,
- expiry: ttl ? Date.now() + ttl : null, // 计算过期时间
- };
- localStorage.setItem(key, JSON.stringify(data));
- },
- /**
- * 获取缓存
- * @param {string} key - 缓存键
- * @returns {*} 缓存值或 null(如果过期或不存在)
- */
- get(key) {
- const data = localStorage.getItem(key);
- if (!data) return null;
- try {
- const { value, expiry } = JSON.parse(data);
- if (expiry && Date.now() > expiry) {
- localStorage.removeItem(key); // 过期删除缓存
- return null;
- }
- return value;
- } catch (e) {
- console.warn("缓存数据解析失败", e);
- return null;
- }
- },
- /**
- * 删除缓存
- * @param {string} key - 缓存键
- */
- remove(key) {
- localStorage.removeItem(key);
- },
- /**
- * 清空所有缓存
- */
- clear() {
- localStorage.clear();
- },
- };
- // 使用示例
- Cache.set("username", "Alice", 5000); // 设置缓存5秒后过期
- console.log(Cache.get("username")); // 5秒内返回 'Alice'
- setTimeout(() => console.log(Cache.get("username")), 6000); // 6秒后返回 null
复制代码 ⚠️ 注意事项
- localStorage 只能存储字符串,因此要使用 JSON.stringify 和 JSON.parse 进行序列化和反序列化。
- localStorage 的存储空间一般有限(大约 5MB)。
- 如果是跨页面使用,请确保在相同的域名下。
2. 使用 sessionStorage 实现数据缓存(适合页面级临时存储)
sessionStorage 是一种浏览器存储机制,它的特点是数据仅在页面会话(session) 期间有效,页面关闭后数据会被清除。- const SessionCache = {
- /**
- * 设置缓存
- * @param {string} key - 缓存键
- * @param {*} value - 缓存值
- * @param {number} ttl - 缓存时间(毫秒)
- */
- set(key, value, ttl) {
- const data = {
- value,
- expiry: ttl ? Date.now() + ttl : null, // 计算过期时间
- };
- sessionStorage.setItem(key, JSON.stringify(data));
- },
- /**
- * 获取缓存
- * @param {string} key - 缓存键
- * @returns {*} 缓存值或 null(如果过期或不存在)
- */
- get(key) {
- const data = sessionStorage.getItem(key);
- if (!data) return null;
- try {
- const { value, expiry } = JSON.parse(data);
- if (expiry && Date.now() > expiry) {
- sessionStorage.removeItem(key); // 缓存已过期,删除
- return null;
- }
- return value;
- } catch (e) {
- console.warn("缓存数据解析失败:", e);
- return null;
- }
- },
- /**
- * 删除缓存
- * @param {string} key - 缓存键
- */
- remove(key) {
- sessionStorage.removeItem(key);
- },
- /**
- * 清空所有缓存
- */
- clear() {
- sessionStorage.clear();
- },
- };
- // **使用示例**
- // 设置缓存,5秒后过期
- SessionCache.set("userToken", "abc123", 5000);
- // 获取缓存
- console.log(SessionCache.get("userToken")); // 5秒内返回 'abc123'
- // 5秒后尝试获取缓存
- setTimeout(() => {
- console.log(SessionCache.get("userToken")); // 返回 null
- }, 6000);
复制代码 ⚠️ 注意事项
- sessionStorage 数据在页面关闭或会话结束时自动清除。
- 在不同的标签页中,sessionStorage 是独立的(不会共享)。
- sessionStorage 的存储空间一般为5MB左右。
- 数据存储在 sessionStorage 时必须经过 JSON.stringify 和 JSON.parse 处理。
3. 使用内存对象实现轻量缓存(适合短期缓存)
- class MemoryCache {
- constructor() {
- this.cache = new Map();
- }
- /**
- * 设置缓存
- * @param {string} key - 缓存键
- * @param {*} value - 缓存值
- * @param {number} ttl - 缓存时间(毫秒)
- */
- set(key, value, ttl) {
- const expiry = ttl ? Date.now() + ttl : null;
- this.cache.set(key, { value, expiry });
- }
- /**
- * 获取缓存
- * @param {string} key - 缓存键
- * @returns {*} 缓存值或 null(如果过期或不存在)
- */
- get(key) {
- const item = this.cache.get(key);
- if (!item) return null;
- if (item.expiry && Date.now() > item.expiry) {
- this.cache.delete(key); // 缓存过期,删除
- return null;
- }
- return item.value;
- }
- /**
- * 删除缓存
- * @param {string} key - 缓存键
- */
- remove(key) {
- this.cache.delete(key);
- }
- /**
- * 清空所有缓存
- */
- clear() {
- this.cache.clear();
- }
- }
- // 使用示例
- const memCache = new MemoryCache();
- memCache.set("token", "abc123", 3000); // 设置缓存3秒后过期
- console.log(memCache.get("token")); // 3秒内返回 'abc123'
- setTimeout(() => console.log(memCache.get("token")), 4000); // 4秒后返回 null
复制代码 4. 使用 IndexedDB 实现持久缓存(支持二进制数据)
- // 初始化 IndexedDB 数据库
- class IndexedDBCache {
- constructor(dbName = "CacheDB", storeName = "CacheStore") {
- this.dbName = dbName;
- this.storeName = storeName;
- this.db = null;
- }
- /**
- * 初始化数据库
- */
- async init() {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open(this.dbName, 1);
- request.onupgradeneeded = (event) => {
- const db = event.target.result;
- if (!db.objectStoreNames.contains(this.storeName)) {
- db.createObjectStore(this.storeName, { keyPath: "key" });
- }
- };
- request.onsuccess = (event) => {
- this.db = event.target.result;
- resolve(this);
- };
- request.onerror = (event) => {
- console.error("IndexedDB 初始化失败:", event.target.error);
- reject(event.target.error);
- };
- });
- }
- /**
- * 获取对象存储
- */
- getObjectStore(mode = "readonly") {
- const transaction = this.db.transaction(this.storeName, mode);
- return transaction.objectStore(this.storeName);
- }
- /**
- * 添加或更新缓存
- * @param {string} key - 缓存键
- * @param {*} value - 缓存值
- * @param {number} ttl - 过期时间(毫秒)
- */
- async set(key, value, ttl) {
- const expiry = ttl ? Date.now() + ttl : null;
- const record = { key, value, expiry };
- return new Promise((resolve, reject) => {
- const store = this.getObjectStore("readwrite");
- const request = store.put(record);
- request.onsuccess = () => resolve(true);
- request.onerror = (event) => {
- console.error("数据写入失败:", event.target.error);
- reject(event.target.error);
- };
- });
- }
- /**
- * 获取缓存
- * @param {string} key - 缓存键
- * @returns {*} 缓存值或 null
- */
- async get(key) {
- return new Promise((resolve, reject) => {
- const store = this.getObjectStore("readonly");
- const request = store.get(key);
- request.onsuccess = (event) => {
- const record = event.target.result;
- if (!record) {
- resolve(null); // 数据不存在
- return;
- }
- if (record.expiry && Date.now() > record.expiry) {
- // 数据过期
- this.delete(key).then(() => resolve(null));
- } else {
- resolve(record.value); // 返回未过期数据
- }
- };
- request.onerror = (event) => {
- console.error("数据读取失败:", event.target.error);
- reject(event.target.error);
- };
- });
- }
- /**
- * 删除缓存
- * @param {string} key - 缓存键
- */
- async delete(key) {
- return new Promise((resolve, reject) => {
- const store = this.getObjectStore("readwrite");
- const request = store.delete(key);
- request.onsuccess = () => resolve(true);
- request.onerror = (event) => {
- console.error("数据删除失败:", event.target.error);
- reject(event.target.error);
- };
- });
- }
- /**
- * 清空缓存
- */
- async clear() {
- return new Promise((resolve, reject) => {
- const store = this.getObjectStore("readwrite");
- const request = store.clear();
- request.onsuccess = () => resolve(true);
- request.onerror = (event) => {
- console.error("缓存清空失败:", event.target.error);
- reject(event.target.error);
- };
- });
- }
- }
- // 使用示例
- (async () => {
- // 创建缓存实例并初始化数据库
- const cache = new IndexedDBCache();
- await cache.init();
- // 设置缓存,数据 5 秒后过期
- await cache.set("userToken", "abc123", 5000);
- console.log("缓存设置完成");
- // 缓存二进制数据
- const binaryData = new Blob(["Hello, IndexedDB"], { type: "text/plain" });
- await cache.set("binary", binaryData, 5000);
- // 获取缓存
- console.log("立即获取:", await cache.get("userToken")); // 输出: abc123
- console.log("立即获取:", await cache.get("binary"));
- // 等待 6 秒后尝试获取缓存
- setTimeout(async () => {
- console.log("6 秒后获取:", await cache.get("userToken")); // 输出: null
- console.log("6 秒后获取:", await cache.get("binary")); // 输出: null
- }, 6000);
- })();
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |