web locks api需配合indexeddb使用,锁名须按资源粒度命名(如note-${id}),必须await navigator.locks.request()及tx.done,不支持localstorage和safari旧版本,降级需服务端幂等+前端乐观校验。

Web Locks API 本身不干预 IndexedDB 写操作,但能防止多页签同时进入「读-改-写」逻辑段——前提是锁名统一、mode 显式设为 'exclusive',且必须 await tx.done,否则锁形同虚设。
锁名必须和业务数据范围严格对齐
锁名不是随便起的字符串,它是跨页签互斥的唯一标识。用静态名如 'db-write' 会导致所有写操作串行化,哪怕修改的是完全无关的用户笔记和系统日志。
- 错:所有写都用
'db-write'→ 一个标签页保存草稿,另一个标签页连加载用户头像都卡住 - 对:按资源粒度命名,比如
`note-${id}`、`user-profile-${userId}`、`cart-${userId}` - 注意:锁名中不能含随机数或时间戳,否则无法形成互斥;也不能漏掉关键维度(如
userId),否则不同用户会误抢同一把锁
必须 await navigator.locks.request(),且回调内必须 await tx.done
很多人只调用 navigator.locks.request() 却不 await 它,或者在回调里只调 put() 就返回,结果锁在事务真正落地前就释放了。
-
await navigator.locks.request()是强制的 —— 不 await,Promise 被丢弃,锁立即释放 -
tx.done是 IndexedDB v3+ 提供的 Promise,必须await tx.done;老版本需手动包装oncomplete事件 - 别信
tx.commit()或store.put()的返回值 —— 它们不表示写入已持久化
localStorage 不能套 Web Locks,别试了
试图用 navigator.locks.request('cart', () => localStorage.setItem(...)) 完全无效。原因很硬:localStorage 是同步阻塞 API,锁插不进执行流。
- 两个标签页可能在毫秒级内先后拿到锁、先后调用
setItem,覆盖照旧 - Web Locks 只能协调异步操作(
fetch、indexedDB、cache等),对同步调用零干预能力 - 真要多页签安全写本地数据,唯一正解是迁移到 IndexedDB + Web Locks 组合
Safari 不支持,降级逻辑不能省
Safari 直到 16.4 才支持 navigator.locks,iOS/macOS 更早版本完全不可用。检测到不支持时,跳过锁逻辑等于裸奔。
- 不能只靠
if ('locks' in navigator)就 return —— 这会让 Safari 用户直接暴露在竞态下 - 推荐降级路径:服务端接口加幂等控制(带唯一
requestId),前端 fallback 到乐观并发校验(比对updatedAt或_rev) - 避免用 localStorage 模拟锁 —— 它没有原子性、无队列、无法协调,只会让问题更隐蔽
最常被忽略的一点:锁只保护“你主动包进去的那段逻辑”,它不会自动拦截 IndexedDB 的任何底层行为。如果你漏了一个写入口(比如某个 Worker 或 iframe 里的更新函数没加锁),整套机制就破防了。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










