web locks api 能解决同源多标签页写冲突,但仅限同一 origin 下,不跨浏览器或设备;需显式指定 mode、合理设计锁名、处理降级逻辑,并为 safari 提供服务端幂等或 localstorage 模拟方案。

Web Locks API 能否真正解决多标签页写冲突
能,但仅限于同一 origin 下的同源标签页之间协调——它不是分布式锁,也不跨浏览器或跨设备生效。如果你的场景是用户在多个标签页里同时编辑同一份数据(比如草稿、购物车、计数器),navigator.locks.request() 是目前唯一原生支持的轻量级协调机制。
request() 的关键参数和常见误用
最常踩的坑是忽略 mode 和没处理锁被抢占时的降级逻辑。默认 mode: 'exclusive' 会阻塞其他请求;而 mode: 'shared' 只适合读操作,写操作必须用 exclusive。
-
navigator.locks.request('cart-update', { mode: 'exclusive' }, async lock => { /* 写操作 */ })—— 必须显式指定mode,否则旧版 Chrome 会静默 fallback 到 shared - 不传
ifAvailable: true时,锁不可用会一直等待,导致 UI 卡住;高交互场景建议加超时:await navigator.locks.request('cart-update', { ifAvailable: true }, cb) - 回调函数必须返回 promise,否则锁会在回调退出后立即释放——别在 callback 里直接写同步代码然后 return
锁名设计与作用域陷阱
锁名不是任意字符串,它是作用域标识符。相同名字的锁在同一个 origin 下全局互斥,但如果你的业务需要按用户或资源 ID 隔离(比如不同用户的购物车不能互相阻塞),锁名必须带唯一标识:
- 错:
'update-cart'—— 所有标签页抢同一个锁,一人编辑,全站冻结 - 对:
`update-cart-${userId}`或`draft-${docId}`—— 按业务维度隔离,避免过度串行 - 注意:锁名不能含空格或控制字符,且长度无硬限制但过长可能影响性能;建议用 URL-safe 字符组合
兼容性与 fallback 方案怎么选
Firefox 114+、Chrome 94+、Edge 94+ 支持完整 API;Safari 完全不支持(截至 iOS 17.5 / macOS 14.5)。如果必须支持 Safari,不能只靠 if ('locks' in navigator) 就跳过逻辑。
- 服务端做幂等写入是底线:所有写请求带客户端生成的
requestId,后端去重或校验版本号(如 ETag / _rev) - 前端可结合
localStorage+storage事件模拟轻量协调(例如写前存lock:cart-123:timestamp,监听到冲突则弹提示),但这不是强一致,仅作友好提示 - 别在锁内做耗时操作(如上传大文件、复杂计算)——锁持有时间越长,竞争概率越高;应只包裹「读-改-写」原子段,把副作用拆到锁外
真正的难点不在 API 调用本身,而在判断哪些操作值得上锁、锁粒度是否合理、以及当锁失败时用户流程是否还能继续——这些没法靠 navigator.locks 自动解决。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










