当前位置: 首页
数据库
Redis使用LocalStorage的实现示例

Redis使用LocalStorage的实现示例

热心网友 时间:2026-04-28
转载

1. 为什么需要 Redis 风格的 LocalStorage 封装

在全栈开发的世界里,一个有趣的“割裂”现象常常让开发者感到困扰:后端处理缓存时,Redis 是当仁不让的主力,其简洁而强大的 API 深受喜爱;而到了前端,LocalStorage 则承担着本地数据存储的重任。问题来了——这两者的操作接口差异可不小。对于习惯了前端开发,又想向全栈领域拓展的同学来说,这往往意味着额外的学习成本和思维切换。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

那么,有没有一种方法能弥合这道鸿沟呢?答案就是封装一个 Redis 风格的 LocalStorage 工具类。这么做,至少能带来几个显而易见的好处:

  • 统一操作体验:前后端缓存操作接口保持一致,降低心智负担。
  • 功能增强:为 LocalStorage 补上原生缺失的“高级”功能,比如精确的过期时间管理、键名通配符查找等。
  • 提升代码质量:集中化的工具类让代码更整洁、更易维护,可读性也大大增强。
  • 面向未来:为日后可能的架构调整(比如将部分缓存逻辑迁移到后端)提前铺平道路,代码适应性更强。

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(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
  }
}

核心设计要点

  1. 数据结构设计:这是整个封装的基石。我们采用 { value, ttl } 这样的结构来包裹实际数据。其中 ttl 字段很关键:它要么是 -1(代表永不过期),要么是一个未来的绝对时间戳(毫秒数)。这样一来,判断过期就变成了简单的时间戳比较。

  2. 过期时间处理:围绕上述数据结构,我们构建了一套完整的生命周期管理:

    • 设置时:根据传入的秒数,计算出精确的过期时间点。
    • 获取时:自动检查是否“寿终正寝”,如果过期则默默清理掉,避免脏数据残留。
    • 查询时:通过 ttl 方法,可以随时查看某个缓存还剩多少“保质期”,非常直观。
  3. 错误处理:LocalStorage 里存储的都是字符串,JSON 解析是必不可少的一步,但也是最容易出错的环节。通过 try-catch 包裹解析逻辑,即使遇到意外格式的数据,也能保证程序不会崩溃,而是返回预设的默认值并清理无效条目,确保了整体的健壮性。

  4. Redis 风格 API:为了让后端同学感到亲切,我们几乎1:1复刻了 Redis 的常用命令:set, get, del, expire, keys, exists。用起来几乎感觉不到差别。

  5. 通配符支持keys 方法是亮点之一。它支持使用 * 进行模糊匹配,比如 user* 可以找出所有以 “user” 开头的键。其内部通过将通配符模式转换为正则表达式来实现,用法和效果都与 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*') // 找到所有USER开头的键
const infoKeys = CacheUtil.keys('*INFO') // 找到所有INFO结尾的键
console.log('用户相关键:', userKeys)
console.log('信息相关键:', infoKeys)

// 快速检查某个关键缓存是否还在
const exists = CacheUtil.exists('USER')
console.log('USER 缓存存在:', exists)

删除操作

// 删除单个缓存项
CacheUtil.del('USER')

// 一键清空,适用于用户退出登录等场景
CacheUtil.flushall()

5. 性能考量与最佳实践

性能考量

  • 存储限制:别忘了,LocalStorage 通常有 5MB 左右的容量上限。存储大型对象或海量数据前,最好先掂量一下。
  • 读取性能:频繁读取体积庞大的 JSON 对象,解析开销不容忽视。合理的建议是:按需存储,把大数据拆分成小块。
  • 过期检查:每次 get 操作都附带一次时间戳比对,虽然开销很小,但在极端高频的调用下也需要纳入考量。
  • JSON 序列化:存进去要 stringify,拿出来要 parse。对于结构复杂、嵌套深的对象,这个成本会线性增长。所以,存储的数据结构还是尽量保持扁平为好。

最佳实践

  • 命名规范:为缓存键设立统一的前缀(比如 APP_USER_INFO),这是避免项目内甚至跨第三方库键名冲突的最简单有效的方法。
  • 数据类型:LocalStorage 不是状态管理库。只存那些真正需要持久化的、关键的用户数据或配置,别把整个应用的状态都往里塞。
  • 过期策略:给临时数据(如表单草稿、会话信息)设置一个合理的过期时间,让系统能自动清理,这是保持存储空间健康的好习惯。
  • 错误处理:工具类内部已经做了基础防护,但在业务代码调用时,尤其是在获取关键配置或用户信息时,考虑一下缓存缺失的降级方案,总是更稳妥的。
  • 安全注意:这一点必须强调:LocalStorage 对同源脚本完全开放,极易受到 XSS 攻击。因此,绝对不要将密码、敏感令牌等机密信息存入其中。
来源:https://www.jb51.net/database/362957civ.htm

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
PostgreSQL开发怎么批量执行多个SQL文件_Navicat特有功能实操

PostgreSQL开发怎么批量执行多个SQL文件_Navicat特有功能实操

Na vicat 不支持批量执行多个 sql 文件,仅能单文件运行且易静默失败;可靠方案是用 psql 命令行配合 shell 循环执行,注意事务隔离、编码统一、跨库拆分及错误中断机制。 Na vicat 里批量执行多个 sql 文件根本不行 先说一个核心判断:Na vicat 本身并没有“选中

时间:2026-04-28 18:08
mysql如何修改数据库名_RenameDatabase失效后的更名方案

mysql如何修改数据库名_RenameDatabase失效后的更名方案

MySQL数据库更名:当RENAME DATABASE成为历史,我们该如何安全操作? 如果你还在寻找一条 RENAME DATABASE old_db TO new_db; 这样的魔法命令,是时候更新一下知识库了。那个曾经短暂存在过的便捷功能,早已被官方彻底放弃。如今,给MySQL数据库改名,更像是

时间:2026-04-28 18:08
SQL如何实现动态决定Update哪些列_利用存储过程参数判定

SQL如何实现动态决定Update哪些列_利用存储过程参数判定

SQL如何实现动态决定Update哪些列:利用存储过程参数判定 在数据库开发中,一个经典的场景是:如何根据传入的参数,动态地决定更新表中的哪些列?换句话说,只更新传了值的字段,没传值的字段保持原样。这可不是简单的字符串拼接SQL能安全解决的,背后涉及到参数有效性判断、执行计划优化以及数据安全等多个层

时间:2026-04-28 18:08
如何配置GlassFish服务器的Oracle数据源

如何配置GlassFish服务器的Oracle数据源

GlassFish 应用服务器配置 Oracle 数据源:关键步骤与避坑指南 在 GlassFish 中配置 Oracle 数据源,看似是标准操作,但几个细节没对上,就可能导致连接测试失败或应用运行时抛出令人头疼的异常。下面这份指南,将帮你梳理从驱动部署到 JNDI 绑定的完整流程,并重点指出那些容

时间:2026-04-28 18:08
mysql如何锁定或禁用特定异常账户_使用ALTER USER ACCOUNT LOCK命令

mysql如何锁定或禁用特定异常账户_使用ALTER USER ACCOUNT LOCK命令

MySQL账户锁定实战指南:从语法细节到版本兼容性 处理异常账户是数据库安全管理的核心任务之一。然而,许多DBA在执行锁定命令后,可能会困惑地发现用户仍然能够成功登录。或者,在低版本的MySQL环境中,根本找不到对应的语法支持。本文将深入解析MySQL中锁定或禁用用户账户的正确方法与最佳实践,帮助您

时间:2026-04-28 18:08
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜
热门教程
更多
  • 游戏攻略
  • 安卓教程
  • 苹果教程
  • 电脑教程