参考 redis 缓存接口封装 localstorage,在全栈项目中保持一致的缓存操作体验,降低前端同学转向全栈开发的心智负担
1. 为什么需要 redis 风格的 localstorage 封装
在全栈开发中,后端通常使用 redis 进行缓存管理,而前端则使用 localstorage 存储本地数据。两者的 api 接口差异较大,这给从前端转向全栈的开发者带来了额外的学习成本。
通过封装一个 redis 风格的 localstorage 工具类,我们可以:
- 保持前后端缓存操作接口一致
- 提供更丰富的缓存管理功能(如过期时间、键匹配等)
- 增强代码的可维护性和可读性
- 为未来可能的后端迁移做好准备
2. 核心功能实现与代码解析
完整工具类实现
export abstract class cacheutil {
/**
* 设置缓存
* @param key 缓存键
* @param value 缓存值
* @param ttl 过期时间(单位:秒),-1 表示永不过期
*/
static set(key: string, value: any, ttl: number = -1) {
const data = { value, ttl: ttl === -1 ? ttl : date.now() + ttl * 1000 }
localstorage.setitem(key, json.stringify(data))
}
/**
* 获取缓存
* @param key 缓存键
* @param defaultvalue 缓存不存在或过期时的默认值
* @returns 缓存值或默认值
*/
static get<t = any>(key: string, defaultvalue: t | null = null): t | null {
try {
const jsonstr = localstorage.getitem(key)
if (!jsonstr) return defaultvalue
const data = json.parse(jsonstr)
if (data.ttl === -1 || date.now() <= data.ttl) return data.value
localstorage.removeitem(key)
return defaultvalue
} catch (error: unknown) {
localstorage.removeitem(key)
return defaultvalue
}
}
/**
* 获取缓存剩余过期时间(秒)
* -1 = 永久有效
* -2 = 已过期/不存在
*/
static ttl(key: string): number {
try {
const item = localstorage.getitem(key)
if (!item) return -2
const data = json.parse(item)
if (data.ttl === -1) return -1
const remaining = data.ttl - date.now()
return remaining > 0 ? math.floor(remaining / 1000) : -2
} catch {
return -2 // 解析失败,视为无效缓存
}
}
/**
* 动态设置缓存过期时间
* @param key 缓存键
* @param ttl 过期时间(秒)
* @returns 是否设置成功
*/
static expire(key: string, ttl: number): boolean {
const value = this.get(key)
if (value === null) return false
this.set(key, value, ttl)
return true
}
/**
* 删除缓存
* @param key 缓存键
*/
static del(key: string) {
localstorage.removeitem(key)
}
/**
* 清空所有缓存
*/
static flushall() {
localstorage.clear()
}
/**
* 查找缓存键(支持通配符 *,和 redis 用法一致)
* @param pattern 匹配规则,例如 user*、*info、*token*,默认 *
* @returns 匹配的键数组
*/
static keys(pattern: string = '*'): string[] {
const allkeys = object.keys(localstorage)
const regex = new regexp(pattern.replace(/\*/g, '.*'))
return allkeys.filter((key) => regex.test(key))
}
/**
* 检查缓存是否存在且未过期
* @param key 缓存键
* @returns 是否存在有效缓存
*/
static exists(key: string): boolean {
return this.get(key) !== null
}
}核心设计要点
数据结构设计:使用
{ value, ttl }结构存储缓存数据,其中ttl为过期时间戳或 -1(永不过期)过期时间处理:
- 设置时计算绝对过期时间戳
- 获取时检查是否过期,过期则自动清理
- 提供
ttl方法查看剩余过期时间
错误处理:通过 try-catch 捕获 json 解析异常,确保缓存操作的稳定性
redis 风格 api:实现了与 redis 相似的
set、get、del、expire、keys、exists等方法通配符支持:
keys方法支持*通配符匹配,与 redis 用法一致
3. 完整 api 接口说明
| 方法 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
| set(key, value, ttl) | 设置缓存 | key: 缓存键 value: 缓存值 ttl: 过期时间(秒),默认 -1 | 无 |
| get(key, defaultvalue) | 获取缓存 | key: 缓存键 defaultvalue: 默认值,默认 null | 缓存值或默认值 |
| ttl(key) | 获取剩余过期时间 | key: 缓存键 | -1: 永久有效 -2: 已过期/不存在 正数: 剩余秒数 |
| expire(key, ttl) | 设置过期时间 | key: 缓存键 ttl: 过期时间(秒) | 是否设置成功 |
| del(key) | 删除缓存 | key: 缓存键 | 无 |
| flushall() | 清空所有缓存 | 无 | 无 |
| keys(pattern) | 查找匹配的键 | pattern: 匹配规则,默认 * | 匹配的键数组 |
| exists(key) | 检查缓存是否存在 | key: 缓存键 | 是否存在有效缓存 |
4. 实战使用示例
基础操作
// 设置缓存,1小时过期
cacheutil.set('user', { id: 1, name: 'john' }, 3600)
// 获取缓存
const user = cacheutil.get('user')
console.log(user) // { id: 1, name: 'john' }过期时间管理
// 续期缓存,设置为2小时过期
cacheutil.expire('user', 7200)
// 查看剩余过期时间
const remainingtime = cacheutil.ttl('user')
console.log(`剩余过期时间:${remainingtime}秒`)键管理
// 通配符查找键
const userkeys = cacheutil.keys('user*')
const infokeys = cacheutil.keys('*info')
console.log('用户相关键:', userkeys)
console.log('信息相关键:', infokeys)
// 检查缓存是否存在
const exists = cacheutil.exists('user')
console.log('user 缓存存在:', exists)删除操作
// 删除指定缓存
cacheutil.del('user')
// 清空所有缓存
cacheutil.flushall()5. 性能考量与最佳实践
性能考量
- 存储限制:localstorage 通常有 5mb 左右的存储限制,避免存储过大的数据
- 读取性能:频繁读取大对象会影响性能,建议将数据合理拆分
- 过期检查:每次
get操作都会检查过期时间,对性能影响较小但需注意 - json 序列化:复杂对象的序列化/反序列化会有性能开销,建议存储结构尽量简单
最佳实践
- 命名规范:使用统一的命名前缀(如
app_)避免键名冲突 - 数据类型:只存储必要的数据,避免存储整个应用状态
- 过期策略:为临时数据设置合理的过期时间,避免占用存储空间
- 错误处理:虽然工具类已做了错误处理,但调用时仍需考虑异常情况
- 安全注意:不要存储敏感信息(如密码、token)到 localstorage
到此这篇关于redis使用localstorage的实现示例的文章就介绍到这了,更多相关redis localstorage内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论