一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何用 Web Locks API 在离线应用里实现多标签页对 IndexedDB 的事务性写保护

时间:2026-07-18 18:02:48 编辑:袖梨 来源:一聚教程网

Web Locks API 本身不直接参与 IndexedDB 事务控制,但通过跨上下文互斥锁解决多标签页并发写入竞态问题;它与IndexedDB事务互补:后者保障单次事务原子性,前者确保多标签对同一逻辑资源的互斥访问。

Web Locks API 本身不直接参与 IndexedDB 的事务控制,但它能解决多标签页并发写入时的竞态问题——比如两个标签同时修改同一条笔记,导致后写入覆盖前写入。它和 IndexedDB 的事务机制是互补关系:IndexedDB 保证单次事务内操作的原子性与一致性;Web Locks 则保证多个上下文(标签页、Worker)对同一逻辑资源的互斥访问。

为什么需要 Web Locks 配合 IndexedDB?

IndexedDB 的事务是“会话级”的,每个标签页打开的数据库连接相互独立。当用户在 Tab A 编辑笔记 A,在 Tab B 同时编辑同一篇笔记 A 并保存,即使两者都用了 readwrite 事务,也无法阻止最终数据被错误覆盖——因为事务之间没有跨上下文锁机制。Web Locks 正是为此设计的轻量级协调原语。

典型场景:离线笔记应用的双标签冲突预防

假设笔记 ID 为 note_123,用户在两个标签页中同时打开并编辑它:

  • Tab A 获取名为 lock:note_123 的独占锁 → 成功 → 开始读取旧数据 → 修改 → 写入 IndexedDB → 释放锁
  • Tab B 尝试获取同名锁 → 被阻塞或立即失败(取决于 mode)→ 可提示“该笔记正在其他窗口编辑”,或排队等待

这样就从源头避免了“最后保存者获胜”这类静默数据丢失。

实际集成步骤(带错误防护)

以下代码片段展示了如何在保存笔记前加锁、操作后释放,并与 IndexedDB 事务衔接:

  • 调用 navigator.locks.request('lock:note_123', { mode: 'exclusive' }, async lock => { ... })
  • 在 lock 回调内打开 IndexedDB 数据库,启动 readwrite 事务
  • 先用 objectStore.get(id) 读取当前版本,校验 updatedAt 时间戳或 version 字段,防止过期写入(乐观锁辅助)
  • 执行 put() 更新,监听事务 oncompleteonerror
  • 无论成功失败,确保锁在事务结束后释放(lock 自动释放,但建议显式处理逻辑边界)

注意事项与常见陷阱

Web Locks 不是万能锁:

  • 锁名必须是字符串,建议按业务实体维度命名(如 lock:user_456lock:cart),避免全局锁影响性能
  • 锁作用域默认是 origin 级,同源下所有标签页、iframe、Service Worker 共享,但不跨域
  • 锁不会持久化,页面关闭或异常退出后自动释放,无需手动清理
  • 不支持嵌套锁,也不提供超时自动释放(需自行用 AbortSignal 控制)
  • 部分旧版 Safari(iOS & macOS ≤14)不支持 Web Locks,务必做降级处理(例如仅用 IndexedDB 乐观校验 + 用户提示)

它不替代 IndexedDB 事务,而是让事务运行在更安全的上下文里。

热门栏目