前端数据缓存的几种方式详细讲解

ops/2025/3/3 9:12:39/

以下是前端数据缓存的完整解决方案,涵盖策略设计、技术实现和性能优化:


一、缓存策略分层设计

缓存策略
内存缓存
持久化缓存
Map/WeakMap
闭包变量
LocalStorage
SessionStorage
IndexedDB
Service Worker

二、核心场景实现方案

1. 高频请求数据缓存(内存缓存
// 使用Map实现LRU缓存
class MemoryCache {constructor(maxSize = 100) {this.cache = new Map()this.maxSize = maxSize}get(key) {const item = this.cache.get(key)if (item) {// 更新访问顺序this.cache.delete(key)this.cache.set(key, item)}return item?.value}set(key, value, ttl = 60_000) {if (this.cache.size >= this.maxSize) {// 删除最久未使用的const oldestKey = this.cache.keys().next().valuethis.cache.delete(oldestKey)}this.cache.set(key, {value,expire: Date.now() + ttl})}clearExpired() {const now = Date.now()for (const [key, { expire }] of this.cache) {if (now > expire) this.cache.delete(key)}}
}// 使用示例
const apiCache = new MemoryCache(50)
2. 持久化重要数据(LocalStorage + 版本控制)
const CACHE_VERSION = 'v1.3'function getCache(key) {try {const data = localStorage.getItem(`${CACHE_VERSION}_${key}`)return data ? JSON.parse(data) : null} catch (error) {console.error('缓存读取失败', error)return null}
}function setCache(key, value, ttl = 3600_000) {const data = {value,expire: Date.now() + ttl,timestamp: Date.now()}localStorage.setItem(`${CACHE_VERSION}_${key}`,JSON.stringify(data))
}// 定时清理过期缓存
setInterval(() => {Object.keys(localStorage).forEach(key => {if (key.startsWith(CACHE_VERSION)) {const data = JSON.parse(localStorage.getItem(key))if (data?.expire < Date.now()) {localStorage.removeItem(key)}}})
}, 60_000)
3. 接口请求缓存策略
const apiCache = new Map()async function cachedFetch(url, options = {}) {const cacheKey = JSON.stringify({ url, options })// 命中缓存if (apiCache.has(cacheKey)) {const { expire, data } = apiCache.get(cacheKey)if (Date.now() < expire) return data.clone()}// 发起真实请求const response = await fetch(url, options)const cloneRes = response.clone()// 缓存新数据apiCache.set(cacheKey, {data: cloneRes,expire: Date.now() + (options.ttl || 300_000)})return response
}

三、高级缓存模式

1. 缓存分层策略
async function getData(key) {// 第一层:内存缓存let data = memoryCache.get(key)if (data) return data// 第二层:本地存储data = getLocalCache(key)if (data) {memoryCache.set(key, data)return data}// 第三层:网络请求data = await fetchData(key)memoryCache.set(key, data)setLocalCache(key, data)return data
}
2. 缓存更新策略
// Stale-While-Revalidate 模式
function swrFetch(url, ttl = 300_000) {const cached = getCache(url)// 立即返回过期数据,后台更新if (cached) {if (Date.now() < cached.expire) {return Promise.resolve(cached.value)} else {fetch(url).then(updateCache).catch(console.error)return cached.value}}// 无缓存则正常请求return fetch(url).then(updateCache)
}

四、性能优化方案

1. Web Worker 缓存处理
// 主线程
const worker = new Worker('cache-worker.js')worker.postMessage({type: 'SET_CACHE',key: 'userData',value: userData
})// Worker线程处理
self.onmessage = (e) => {if (e.data.type === 'SET_CACHE') {IndexedDB.set(e.data.key, e.data.value)}
}
2. 缓存压缩策略
function compressData(data) {const str = JSON.stringify(data)const compressed = LZString.compress(str)return compressed
}function decompressData(compressed) {const str = LZString.decompress(compressed)return JSON.parse(str)
}

五、缓存监控与调试

1. 缓存命中率统计
const cacheStats = {total: 0,hits: 0,misses: 0
}function trackCacheAccess(isHit) {cacheStats.total++isHit ? cacheStats.hits++ : cacheStats.misses++if (cacheStats.total % 100 === 0) {console.log(`缓存命中率: ${(cacheStats.hits/cacheStats.total*100).toFixed(1)}%`)}
}
2. Chrome DevTools 调试
// 暴露缓存接口到全局
window.__debugCache = {clear: () => {memoryCache.clear()localStorage.clear()},stats: () => cacheStats
}

六、最佳实践建议

  1. 缓存Key设计原则

    // 好的Key设计示例
    const getCacheKey = (apiPath, params) => {const sortedParams = Object.keys(params).sort().map(k => `${k}=${params[k]}`).join('&')return `api_${apiPath}?${sortedParams}`
    }
    
  2. 敏感数据处理

    // 加密敏感缓存
    import CryptoJS from 'crypto-js'function secureSet(key, value) {const encrypted = CryptoJS.AES.encrypt(JSON.stringify(value),process.env.CACHE_SECRET).toString()localStorage.setItem(key, encrypted)
    }
    
  3. 缓存容量控制

    // IndexedDB容量监测
    navigator.storage.estimate().then(estimate => {console.log(`已使用: ${estimate.usage/1024/1024}MB`)console.log(`限额: ${estimate.quota/1024/1024}MB`)
    })
    

七、不同场景推荐方案

场景推荐方案优势注意事项
高频更新数据内存缓存访问速度快需设置合理TTL
大型数据集IndexedDB支持结构化存储需处理版本迁移
离线优先Service Worker网络不可用仍可访问需处理缓存更新
敏感信息加密存储数据安全加解密性能损耗

通过合理使用这些缓存策略,可以实现:

  • 首屏加载速度提升 30%-70%
  • 接口请求量减少 40%+ 📉
  • 离线场景正常使用 📴
  • 流量消耗显著降低 🌐

建议结合业务需求选择缓存层级,并定期通过 window.performance.memory 监控内存使用情况,避免过度缓存导致内存泄漏。


http://www.ppmy.cn/ops/162724.html

相关文章

16.4 LangChain LCEL 接口全解析:同步、异步与批处理的正确打开方式

LangChain LCEL 接口全解析:同步、异步与批处理的正确打开方式 关键词:LCEL 接口设计、同步异步编程、批量处理优化、生产级并发控制、流式传输原理 1. 三大接口核心定位与性能特征 1.1 接口对比矩阵 接口类型调用方法适用场景吞吐量资源消耗同步接口invoke()实时交互、低并…

常见的正则匹配规则

目录 1&#xff0c;匹配数字2&#xff0c;匹配字母3&#xff0c;匹配字母和数字4&#xff0c;匹配邮箱地址5&#xff0c;匹配URL6&#xff0c;匹配身份证号7&#xff0c;匹配手机号8&#xff0c;匹配日期9&#xff0c;匹配IP地址10&#xff0c;匹配密码强度11&#xff0c;匹配空…

新时代,科技助力运动旅游开启新潮流

新时代&#xff0c;科技助力运动旅游开启新潮流 运动&科技旅游&科技 其实说到运动旅游&#xff0c;这应该是两个方面&#xff1a;运动和旅游&#xff0c;那么下面就从运动和旅游两个方面来理解一下个人认为的哪些科技手段可以助力行程。 运动&科技 说到运动&…

【汽车ECU电控数据管理篇】DCM文件格式解析篇章

一、什么是DCM文件 DCM&#xff08;Data Conservation Format&#xff09;是一种标定数据文件格式&#xff0c;文件后缀为 .dcm。它主要用于存储标定数据&#xff0c;记录标定变量的实际值及其与 A2L 文件中定义的变量之间的映射关系。DCM 文件通常由标定工程师在上位机软件&am…

【Java】JDK17新特性

JEP 356&#xff1a;增强型伪随机数生成器 地址&#xff1a;356 JDK 17 之前&#xff0c;我们可以借助 Random、ThreadLocalRandom 和SplittableRandom 来生成随机数。不过&#xff0c;这 3 个类都各有缺陷&#xff0c;且缺少常见的伪随机算法支持。 jdk17中为伪随机数生成器…

【AIGC系列】4:Stable Diffusion应用实践和代码分析

AIGC系列博文&#xff1a; 【AIGC系列】1&#xff1a;自编码器&#xff08;AutoEncoder, AE&#xff09; 【AIGC系列】2&#xff1a;DALLE 2模型介绍&#xff08;内含扩散模型介绍&#xff09; 【AIGC系列】3&#xff1a;Stable Diffusion模型原理介绍 【AIGC系列】4&#xff1…

(未完)3D Shape Tokenization

https://arxiv.org/abs/2412.15618 3D Shape Tokenization 摘要 我们引入了形状标记&#xff08;Shape Tokens&#xff09;&#xff0c;这是一种连续、紧凑且易于融入机器学习模型的3D表示方法。形状标记作为3D流匹配模型中的条件向量&#xff0c;代表形状信息。流匹配模型通…

【 开发知识点 一 】 随机数生成器 /dev/urandom 和 /dev/random

文章目录 一、随机数生成器 是什么 ?二、为什么 需要 随机数生成器 ?三、随机数生成器 基本原理四、随机数生成器 三个输出接口五、随机生成器 应用1、简单应用2、项目应用一、随机数生成器 是什么 ? /dev/random 和 /dev/urandom 是 Linux 上的字符设备文件,它们是随机数…