Web Locks API 可在同源多标签页间实现对共享资源的排他性访问控制,需用含业务标识的URL-safe锁名、显式设mode:'exclusive'和ifAvailable:true,Safari不支持须服务端幂等兜底。

可以通过 navigator.locks.request() 在多个同源页面实例间实现对共享资源的异步、排他性访问控制,避免竞态条件。核心在于利用浏览器原生的 Lock Manager API(需 HTTPS 或 localhost),以锁名作为资源标识,自动排队、释放和超时管理。
确保环境支持并获取锁管理器
Lock Manager API 目前在 Chrome、Edge、Firefox(部分支持)中可用,要求页面运行在安全上下文(HTTPS 或 localhost)。无需手动初始化,直接使用 navigator.locks:
- 检查是否可用:
if ('locks' in navigator) { ... } - 不支持时需降级(如 localStorage 标记 + 轮询,但无法真正互斥)
用唯一锁名标识共享资源
锁名是字符串,必须全局唯一且稳定——建议与资源逻辑强绑定,例如:
-
"user-preferences-write"(多页同时保存用户设置) -
"sync-queue-flush"(多个标签页触发同一同步队列提交) - 避免动态生成(如含时间戳或随机数),否则无法达成互斥
请求锁并执行临界区操作
request() 返回 Promise,在获得锁后才执行回调;其他实例会排队等待,或被拒绝(取决于选项):
navigator.locks.request('my-resource', async (lock) => {
// ✅ 此处已获得独占锁
await saveToIndexedDB(data); // 或调用 fetch、写 localStorage 等
await broadcastUpdate(); // 如通过 BroadcastChannel 通知其他页
// ? 锁在回调退出后自动释放(包括抛错、return、await 后)
});
- 支持
mode: 'exclusive'(默认)或'shared'(适合读多写少场景) - 可设
ifAvailable: true实现“有锁就干,没锁跳过” - 可设
steal: true允许主动抢占(慎用,可能中断他人操作) - 不建议在锁内做长时间同步操作(如大数组遍历),应尽快完成 I/O 并释放
处理锁冲突与降级策略
锁请求可能因超时、被抢占或页面卸载而失败,需显式捕获错误:
- Promise 拒绝时通常为
DOMException,name === 'AbortError'表示被取消或超时 - 可配合
signal(AbortSignal)实现自定义超时:{ signal: AbortSignal.timeout(3000) } - 失败后可重试(带退避)、提示用户“正在其他窗口操作”,或启用只读降级路径
Lock Manager 不提供持久化或跨浏览器同步能力,仅限同源、同设备、同浏览器进程内的协调。若需更广范围控制(如多端协同),仍需服务端仲裁。

















