无需登录 数据私有 本地保存

Web Locks API 探索器 - 跨标签页资源协调

11
0
0
0

Web Locks API 探索器

跨标签页资源协调 · 可视化锁管理 · 实时状态监控。在同一浏览器中打开多个标签页即可体验真正的跨上下文锁协调。

快速演示场景
标签页 A(当前页面) 主上下文
当前持有的锁:
暂无持有的锁
标签页 B(iframe 模拟) 辅助上下文 通过 BroadcastChannel 通信
iframe 状态:
全局锁状态监控(navigator.locks.query())
已持有的锁 (Held)
等待中的锁 (Pending)
自动每 1.5 秒刷新 · 最后刷新:-
操作日志
--:--:-- Web Locks API 探索器已就绪。使用上方控件或预设场景开始探索。
常见问题 & 知识点(FAQ)

Web Locks API 是一种浏览器原生提供的资源协调机制,允许在不同标签页、窗口或 iframe 之间安全地协调对共享资源(如 IndexedDB、localStorage、网络请求等)的访问。它通过 navigator.locks.request() 方法请求锁,确保同一时间只有一个上下文可以访问被锁保护的资源,有效避免竞态条件(race condition)。与传统的基于 localStorage 的锁方案相比,Web Locks API 更加可靠、高效,且由浏览器原生支持,不会受到页面冻结或崩溃的影响。

独占锁(exclusive):同一时间只有一个上下文可以持有该名称的锁。适用于写操作,如更新 IndexedDB 数据、修改共享状态等。当独占锁被持有时,任何其他锁请求(无论是独占还是共享)都必须等待。

共享锁(shared):允许多个上下文同时持有同一名称的锁,但前提是所有这些请求都是共享模式。适用于读操作。当共享锁被持有时,其他共享请求可以同时获取锁,但独占请求必须等待所有共享锁释放。这种设计类似于读写锁(read-write lock)模式。

当设置 { ifAvailable: true } 时,如果锁无法立即获取(被其他上下文持有),请求不会进入等待队列,而是立即返回 null。这使得开发者可以实现"尝试获取锁,如果不行就跳过"的非阻塞模式。典型场景:定期后台同步任务——如果锁可用就执行同步,如果其他标签页正在同步则跳过本次,避免重复工作。

{ steal: true } 允许强制夺取其他上下文持有的锁。被夺锁的上下文其回调函数中的 Promise 会被拒绝(抛出 AbortError),从而可以执行清理逻辑。这个功能强大但危险——滥用可能导致数据不一致。仅在确定需要中断其他操作时才使用,例如用户主动取消了一个长时间运行的任务。注意:部分浏览器可能不完全支持此选项。

通过 AbortControllersignal 选项可以给锁请求设置超时:
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5000);
navigator.locks.request('key', { signal: ctrl.signal }, async (lock) => { ... });

当超时触发时,如果锁尚未获取,请求会被取消并抛出 AbortError。如果已经获取锁,则锁不会被自动释放——需要在回调中监听 signal 的 abort 事件来手动处理。本工具的超时设置即基于此机制实现。

Web Locks API 在现代浏览器中获得了广泛支持:Chrome 69+、Edge 79+、Opera 56+、Samsung Internet 10+ 均完整支持。Firefox 96+ 也提供了支持。Safari 从 15.6 版本开始支持该 API,但在某些旧版本中可能不可用。对于不支持的环境,可以考虑使用 navigator.locks 的特性检测来优雅降级,或使用基于 IndexedDB / localStorage 的 polyfill 方案。

1. 原子性:Web Locks API 的锁操作是原子的,不存在 localStorage 方案中的检查-设置竞态。
2. 自动释放:当标签页关闭或崩溃时,锁自动释放,不会留下死锁。
3. 队列管理:浏览器自动维护等待队列,按 FIFO 顺序公平分配锁。
4. 性能:无需轮询,基于事件驱动,更省资源。
5. 与 Service Worker 集成:可在 Service Worker 中使用,实现更强大的后台协调能力。

多标签页数据同步:确保同一时间只有一个标签页更新 IndexedDB,避免数据冲突。
单例后台任务:多个标签页中只有一个执行定时数据拉取,节省带宽和计算资源。
离线优先应用:协调 Service Worker 和页面之间的缓存更新操作。
协作编辑:在多个窗口间协调文档编辑状态。
令牌刷新:确保多个并发请求中只有一个触发令牌刷新,避免重复刷新。

Web Locks API 的设计本身就减少了死锁风险:锁与浏览器上下文生命周期绑定,标签页关闭时自动释放所有锁;支持 AbortSignal 超时机制;navigator.locks.query() 可检查锁状态。最佳实践:始终设置合理的超时,避免在锁回调中执行过长操作,使用 ifAvailable 进行非阻塞尝试,避免嵌套锁请求(在持有锁A时请求锁B可能导致死锁)。如果确实需要多个锁,应始终以相同顺序获取。

该方法返回一个 Promise,解析为包含两个数组的对象:{ held: [], pending: [] }
held 数组包含当前所有已获取的锁信息,每个锁有 name(锁名称)、mode('exclusive'或'shared')、clientId(持有者的唯一标识)。
pending 数组包含等待队列中的锁请求,同样包含 namemode 属性。这个 API 对于调试和监控锁状态非常有用,本工具的状态监控面板就是基于定期调用此方法实现的。