indexeddb可通过封装写操作+自定义事件系统实现观察者模式:统一拦截add/put/delete,事务oncomplete后触发store-updated事件,支持按store/key/operation过滤,并可结合diff提供细粒度变更通知。

IndexedDB 本身不提供内置的观察者机制,但可以通过封装数据库操作 + 自定义事件系统,实现类似“数据变更通知”的观察者模式。核心思路是:所有写操作(add、put、delete)都经过统一入口,并在成功后触发对应 store 的变更事件。
封装数据库操作,统一触发变更事件
不要直接调用 objectStore.put() 等原生方法,而是封装一个带通知能力的写入层:
- 为每个 objectStore 创建一个事件发射器(如用
EventTarget或轻量 EventEmitter) - 封装
updateItem(storeName, key, value)、deleteItem(storeName, key)等方法 - 每次写操作完成(onSuccess)后,派发自定义事件,例如
store-updated,并附带 store 名称、操作类型、主键和新/旧值(如可获取)
监听变更事件,注册观察者回调
观察者通过标准事件监听方式订阅感兴趣的数据变化:
- 使用
eventTarget.addEventListener('store-updated', handler)监听全局或指定 store 的更新 - 可在 handler 中做 UI 刷新、状态同步、日志记录等响应动作
- 支持按 storeName、key 或 operationType 过滤,例如只关心
'users'store 中 id 为 101 的更新
处理事务边界与错误场景
IndexedDB 的事务具有原子性,需确保事件只在事务真正提交后触发:
- 监听事务的
oncomplete而非单个请求的onsuccess,避免因后续请求失败导致误通知 - 若事务中多个 store 被修改,可批量触发多个事件,或合并为一个复合事件
- 发生
onabort或onerror时不触发任何变更事件,保持语义一致性
进阶:支持自动 diff 与细粒度通知
若需知道具体字段变化(如仅 email 字段被修改),可在 update 前读取旧值进行比对:
- 在
updateItem内部先执行get(key)获取当前值(同一事务内) - 深比较新旧对象,生成变更路径列表(如
['email'])或 patch 对象 - 将 diff 结果作为 detail 传入事件,供观察者精准响应
不复杂但容易忽略的是事务生命周期与事件时机的匹配——错把请求级成功当事务级成功,会导致脏通知。只要守住 transaction.oncomplete 这个关口,观察者模式就能稳定可靠地跑在 IndexedDB 之上。











