IndexedDB 缓存报表中间计算数据的核心是按筛选参数生成唯一 key 并管理过期、并发与降级:先排序参数再序列化生成 key,写入时附加 timestamp 和 ttl,读取时检查有效性并自动回退计算,定期按时间清理超限缓存。

用 IndexedDB 缓存报表导出的中间计算数据,核心是把耗时的计算结果(比如聚合、分组、格式转换后的数据)存成键值对,下次导出相同条件时直接读取,跳过重复计算。关键不在“存”,而在“何时存、存什么、怎么查、怎么更新”。
明确缓存粒度:按查询条件生成唯一 key
不要缓存整个报表,而是按用户筛选参数(如日期范围、部门 ID、指标维度)生成可复用的缓存 key。推荐用 JSON.stringify + hash(如简单 MD5 或 XXHash),或直接拼接规范化字符串:
- 把参数对象先排序再序列化,避免 {a:1,b:2} 和 {b:2,a:1} 生成不同 key
- 排除不影响计算的字段(如页码、排序方向),只保留影响中间结果的字段
- 示例 key:
"export_cache_v2_20240101_20241231_dept123_sales"
封装带过期和写入控制的存储逻辑
IndexedDB 默认无过期机制,需手动加时间戳字段,并在读取时判断是否过期(比如 10 分钟内有效)。同时避免并发写入冲突:
- 写入前先用
get()检查是否存在;存在且未过期则跳过计算 - 写入时用
put()覆盖旧值,附带timestamp和ttl(如Date.now() + 600000) - 导出触发计算前,加个轻量级锁(如用
Promise队列或标记位),防止同一 key 多次重复计算
读取时降级处理:缓存失效自动回退到计算
读取缓存不是“必须命中”,而是“优先尝试”。流程应为:查缓存 → 命中且有效 → 直接用;否则 → 执行计算 → 写入缓存 → 返回结果:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 不因缓存失败中断导出流程,保证功能可用性
- 读取失败(如 DB 报错、版本升级导致 store 不存在)时静默降级,不抛错
- 可在控制台或埋点记录缓存命中率,用于后续优化
定期清理与容量管理
长期运行可能积累大量缓存,需主动控制体积:
- 每次写入前检查当前库大小(用
navigator.storage.estimate()获取 quota 信息) - 设置上限(如最多存 50 条),超限时按时间戳删除最旧的几条
- 用户切换账号或清除本地数据时,调用
deleteDatabase或清空 objectStore
不复杂但容易忽略:缓存的是“中间数据”,不是最终 Excel 文件。导出仍需前端生成 blob 或调用 SheetJS,只是省掉了数据加工环节。

















