web locks api无法实现磁盘原子写入,仅能协调indexeddb等沙箱存储的跨上下文互斥;其锁名需带业务标识、须await事务完成,且safari不支持时需服务端幂等兜底。

你真正能控制的,只有 IndexedDB、Cache API、localStorage 这类受沙箱约束的存储机制;而 Web Locks 只能在这些机制之上做跨上下文互斥协调,它本身不操作磁盘,也不改变底层存储的持久化语义。
为什么 navigator.locks.request() 对“磁盘写入”完全无效
常见误用:navigator.locks.request('disk-write', () => { fs.writeFileSync('/tmp/data.txt', 'hello') }) —— 这段代码根本跑不起来,因为 fs.writeFileSync 在浏览器环境里不存在,Node.js 的 fs 模块不可用。
- 浏览器中没有
fs、writeFile、open()等系统级 I/O API,所有文件操作必须通过FileSystemAccessAPI(仅限用户主动选择的文件)或封装在 IndexedDB / Cache 中 -
navigator.locks是 Promise-based 异步锁,只能包裹异步操作;而所谓“磁盘写入”若真存在,也必然是同步阻塞行为(如 localStorage),锁对其无插入点 - 即使未来有
showSaveFilePicker()+writable.getWriter().write()流式写入,那也只是单次用户授权后的文件覆盖,不是任意路径的原子磁盘写入
你实际能原子化的,只有 IndexedDB 事务 + Web Locks 组合
如果你的目标是“多标签页/Worker 同时更新同一份数据,不丢不覆”,唯一可行路径是:
- 用
indexedDB.open()打开数据库,事务设为'readwrite',利用其单事务原子性 - 把整个「读旧值 → 计算新值 →
put()写入 →await tx.done」包进navigator.locks.request(..., { mode: 'exclusive' }) - 锁名必须带业务标识,例如
`user-settings-${userId}`,避免全局锁导致无关操作互相阻塞 - 务必
await tx.done,否则锁在事务提交前就释放,竞态照旧
Service Worker 和主线程共用一把锁时要注意什么
两者同源即可共享锁管理器,但容易踩的坑很具体:
- 锁名必须完全一致(包括大小写、连字符),
'cache-update'和'Cache-Update'是两把锁 - Service Worker 的
fetch事件中调用navigator.locks.request是合法的,但不能在install或activate阶段提前申请,那时锁管理器可能未就绪 - 主线程和 SW 同时请求同一把锁时,谁先拿到取决于排队顺序,但不会死锁;不过若 SW 在锁内做
cache.put(),而主线程又在锁内等该 cache 响应,就可能形成隐式依赖循环 - 不要在锁回调里调用
self.skipWaiting()或clients.claim(),这些操作不涉及共享资源,加锁纯属冗余
'global-lock'),并发直接归零;锁太细(比如每次 put() 都单独锁),锁调度开销反超收益。而一旦 Safari 用户进入流程(至今仍不支持 navigator.locks),所有这些设计都得靠服务端幂等 + 客户端冲突提示兜底——这点常被忽略。大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










