如何通过 navigator.locks 避免多窗口本地缓存数据写入冲突协调?
- 内容介绍
- 相关推荐
本文共计859个文字,预计阅读时间需要4分钟。
navigator.locks不操作数据,也不涉及预缓存写入逻辑,它仅提供跨窗口(同源)的轻量级协调信号。要实现多窗口对本地缓存的并发读写冲突,关键不在于加锁这个动作,而是通过读取当前缓存+计算新值+写回缓存这一完整逻辑,在锁的异步回调中确保所有窗口都遵守同一套规则。
必须搭配支持事务的存储方案
localStorage 不行——它是同步、无事务、无原子性的 API,锁根本插不进执行流。一旦调用 setItem,写入立刻发生,锁只是事后签到。
- ✅ 正确选择:IndexedDB。它原生支持 readwrite 事务,能保证单次 put/delete 操作的原子性;配合 navigator.locks,可实现“串行化读-改-写”
- ⚠️ 警惕陷阱:不要只锁 store.put() 这一行。必须从 openDB() 开始,到 await tx.done 结束,全程 await,否则事务可能在锁释放后才提交,失去保护意义
- ❌ 避免替代方案:用 localStorage + storage 事件模拟锁,仅适合提示用户“别人正在编辑”,无法防止竞态覆盖,不是强一致方案
锁名设计决定协调粒度
锁名不是标签,而是作用域标识符。相同名字的锁,在整个 origin 下互斥;名字不同,就形同虚设。
本文共计859个文字,预计阅读时间需要4分钟。
navigator.locks不操作数据,也不涉及预缓存写入逻辑,它仅提供跨窗口(同源)的轻量级协调信号。要实现多窗口对本地缓存的并发读写冲突,关键不在于加锁这个动作,而是通过读取当前缓存+计算新值+写回缓存这一完整逻辑,在锁的异步回调中确保所有窗口都遵守同一套规则。
必须搭配支持事务的存储方案
localStorage 不行——它是同步、无事务、无原子性的 API,锁根本插不进执行流。一旦调用 setItem,写入立刻发生,锁只是事后签到。
- ✅ 正确选择:IndexedDB。它原生支持 readwrite 事务,能保证单次 put/delete 操作的原子性;配合 navigator.locks,可实现“串行化读-改-写”
- ⚠️ 警惕陷阱:不要只锁 store.put() 这一行。必须从 openDB() 开始,到 await tx.done 结束,全程 await,否则事务可能在锁释放后才提交,失去保护意义
- ❌ 避免替代方案:用 localStorage + storage 事件模拟锁,仅适合提示用户“别人正在编辑”,无法防止竞态覆盖,不是强一致方案
锁名设计决定协调粒度
锁名不是标签,而是作用域标识符。相同名字的锁,在整个 origin 下互斥;名字不同,就形同虚设。

