Web Locks API 是浏览器原生轻量级并发协调机制,专为解决同源多标签页/Worker对共享资源(如 IndexedDB、localStorage)的竞态问题而设计;需锁名精准(如user-cart-${userId})、模式明确(写操作用{mode:'exclusive',ifavailable:true})、范围最小(仅包“读–改–写”核心逻辑)、释放可靠(await tx.done);Safari 不支持,服务端幂等为兜底。
web locks api 是浏览器提供的原生机制,用于在同源的多个页面或 worker 之间协调对共享资源的访问,避免竞态条件。它不提供分布式锁或跨域锁能力,也不持久化,只在当前 browsing context(如标签页、worker)生命周期内有效。
基础用法:请求并持有锁
使用 navigator.locks.request() 请求锁,传入锁名和回调函数。浏览器会排队等待锁可用,然后执行回调。锁在回调返回 Promise 后自动释放(或显式调用 release())。
- 锁名是字符串,相同名字代表同一把逻辑锁;不同名字互不影响
- 回调必须返回 Promise,锁会在该 Promise settle(fulfill/reject)后释放
- 若页面关闭或 Worker 终止,未释放的锁会自动清理
示例:防止多个标签页同时提交表单
navigator.locks.request('submit-lock', async (lock) => {
// 此处已获得锁,可安全执行临界操作
const response = await fetch('/api/submit', { method: 'POST' });
return response.json();
}).catch(err => console.error('获取锁失败或操作出错', err));
处理锁竞争与超时
默认情况下,request() 会一直等待锁释放。实际项目中建议设置超时,避免无限阻塞。
- 通过
ifAvailable选项实现“立即尝试,拿不到就放弃” - 手动控制等待时间:用
AbortController配合signal参数 - 注意:API 本身不支持毫秒级 timeout 参数,需自行封装取消逻辑
示例:带 3 秒超时的锁请求
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const controller = new AbortController();
setTimeout(() => controller.abort(), 3000);
try {
await navigator.locks.request('data-sync', { signal: controller.signal }, async lock => {
await syncUserData();
});
} catch (err) {
if (err.name === 'AbortError') {
console.log('等待锁超时,跳过同步');
} else {
console.error('锁操作失败', err);
}
}
跨上下文协作:页面 + Service Worker 共享锁
同一个 origin 下的页面、iframe、Web Worker 和 Service Worker 可以通过相同锁名协调。适合需要后台同步的场景(如离线数据写入)。
- Service Worker 中同样调用
self.locks.request() - 锁不是全局独占——每个上下文独立请求,但同名锁互斥
- 适合保护 IndexedDB 写操作、localStorage 修改等易冲突操作
示例:页面触发更新,SW 负责落库,用锁避免重复写
// 页面中
navigator.locks.request('db-write', async () => {
await fetch('/api/update');
});
// Service Worker 中监听 fetch 并写库
self.addEventListener('fetch', event => {
if (event.request.url.includes('/api/update')) {
event.respondWith(
self.locks.request('db-write', async () => {
const db = await openDB('my-app');
await db.put('cache', { updated: Date.now() });
})
);
}
});
注意事项与常见误区
Web Locks API 简单但容易误用。关键点在于理解它的作用边界:
- 仅限同源,无法跨子域或跨协议(http/https 视为不同源)
- 锁不保证执行顺序,只保证同一时刻最多一个回调在运行
- 不能替代服务端锁——它只解决客户端并发,后端仍需自身并发控制
- 不要在锁内做长时间同步操作(如大数组遍历),会阻塞其他请求
如果发现锁没生效,先检查是否所有参与方都用了完全相同的锁名(包括大小写和空格),并确认它们处于同一 origin 且都支持该 API(Chrome 84+、Edge 84+、Firefox 109+,Safari 尚未支持)。

















