本文目录导读:

- 使用
localStorage+ 时间戳(最常用) - 使用 IndexedDB(适合大量结构化数据)
- 使用
sessionStorage(页面会话级缓存) - 使用 Cookie(服务端+客户端双端可用)
- 使用 Cache API(Service Worker 专用)
- 最佳实践建议
- 自动清理过期数据的工具函数
设置本地缓存时效通常需要根据缓存类型采用不同方法,以下是几种常见方案及实现代码:
使用 localStorage + 时间戳(最常用)
// 设置缓存(带过期时间)
function setCache(key, value, ttl) {
const data = {
value: value,
expire: Date.now() + ttl * 1000 // ttl 单位:秒
}
localStorage.setItem(key, JSON.stringify(data))
}
// 获取缓存(自动判断是否过期)
function getCache(key) {
const str = localStorage.getItem(key)
if (!str) return null
try {
const data = JSON.parse(str)
if (Date.now() > data.expire) {
localStorage.removeItem(key) // 过期自动删除
return null
}
return data.value
} catch {
return null
}
}
// 使用示例:缓存10分钟(600秒)
setCache('user_info', {name: '张三'}, 600)
const info = getCache('user_info')
优点:简单、兼容性好
缺点:需要自行清除过期数据
使用 IndexedDB(适合大量结构化数据)
// 封装一个带有过期时间的 IndexedDB 工具
class IndexedDBCache {
constructor(dbName, storeName) {
this.dbName = dbName
this.storeName = storeName
this.db = null
}
async open() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, 1)
request.onupgradeneeded = (e) => {
const db = e.target.result
if (!db.objectStoreNames.contains(this.storeName)) {
const store = db.createObjectStore(this.storeName, { keyPath: 'key' })
store.createIndex('expire', 'expire', { unique: false })
}
}
request.onsuccess = (e) => {
this.db = e.target.result
resolve()
}
request.onerror = reject
})
}
async set(key, value, ttl) {
await this.ensureOpen()
const transaction = this.db.transaction(this.storeName, 'readwrite')
const store = transaction.objectStore(this.storeName)
const data = {
key,
value,
expire: Date.now() + ttl * 1000
}
store.put(data)
}
async get(key) {
await this.ensureOpen()
return new Promise((resolve) => {
const transaction = this.db.transaction(this.storeName, 'readonly')
const store = transaction.objectStore(this.storeName)
const request = store.get(key)
request.onsuccess = (e) => {
const data = e.target.result
if (!data) { resolve(null); return }
if (Date.now() > data.expire) {
this.delete(key)
resolve(null)
} else {
resolve(data.value)
}
}
request.onerror = () => resolve(null)
})
}
async delete(key) {
await this.ensureOpen()
const transaction = this.db.transaction(this.storeName, 'readwrite')
const store = transaction.objectStore(this.storeName)
store.delete(key)
}
async ensureOpen() {
if (!this.db) await this.open()
}
}
// 使用示例
const dbCache = new IndexedDBCache('myApp', 'cache')
await dbCache.set('api_data', { list: [1,2,3] }, 300) // 5分钟
const data = await dbCache.get('api_data')
优点:容量大(>5MB)、支持复杂查询、自动清理过期数据
缺点:API 较复杂、需要异步处理
使用 sessionStorage(页面会话级缓存)
// 页面关闭即失效,无需手动设置时效
sessionStorage.setItem('temp_key', '仅当前标签页有效')
// 如果需要自定义过期时间(需配合时间戳,同 localStorage 方案)
适用场景:表单暂存、页面间传递临时数据
使用 Cookie(服务端+客户端双端可用)
// 设置带过期时间的 Cookie(expires 是绝对时间)
document.cookie = `token=abc123; max-age=${3600}; path=/` // 1小时后过期
// 或使用 expires 字符串
document.cookie = `token=abc123; expires=${new Date(Date.now() + 3600000).toUTCString()}; path=/`
注意:Cookie 有 4KB 大小限制,每次请求都会自动携带
使用 Cache API(Service Worker 专用)
// 在 Service Worker 中设置缓存策略
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
// 缓存未命中时从网络获取
return response || fetch(event.request).then((res) => {
const clone = res.clone()
caches.open('v1').then((cache) => {
cache.put(event.request, clone)
})
return res
})
})
)
})
最佳实践建议
| 数据类型 | 缓存方案 | 时效设置 |
|---|---|---|
| 简单的字符串/JSON | localStorage + 时间戳 |
按 TTL 秒数 |
| 大量数据或文件 | IndexedDB | 每条记录独立过期 |
| 用户登录态 | Cookie | 服务端设置 max-age |
| 仅当前页面有效 | sessionStorage |
页面关闭即失效 |
| 离线资源 | Cache API + Service Worker | 使用 cache.addAll 时指定版本 |
自动清理过期数据的工具函数
// 定期清理所有 localStorage 中的过期项
function clearExpiredKeys() {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i)
try {
const data = JSON.parse(localStorage.getItem(key))
if (data && data.expire && Date.now() > data.expire) {
localStorage.removeItem(key)
}
} catch { /* 非 JSON 格式跳过 */ }
}
}
// 页面加载时执行一次
window.addEventListener('load', clearExpiredKeys)
// 或定时执行(例如每10分钟)
setInterval(clearExpiredKeys, 600000)
选择哪种方案取决于你的数据量、持久性要求、是否需要服务端参与等场景,如果只是简单的前端缓存,推荐使用 localStorage + 时间戳 方案,实现简单且足够满足大部分需求。