Web Locks API是浏览器原生提供的用于管理共享资源并发访问的接口,开发者可以通过js调用该API对指定资源加锁,确保同一时间只有一个执行上下文能够操作目标资源,有效避免多标签页、多异步任务并发修改数据带来的冲突问题。

Web Locks API基础操作方法
Web Locks API的核心是通过navigator.locks.request方法申请锁,该方法接收锁名称、可选配置、回调函数三个参数,回调函数中执行需要加锁的逻辑,逻辑执行完成后锁会自动释放。如果需要手动释放锁,也可以使用navigator.locks.release方法。
下面是一个最基础的加锁操作示例,对名为test_lock的资源加锁,在回调中执行资源操作:
// 申请名为test_lock的锁
navigator.locks.request('test_lock', async (lock) => {
// 锁获取成功,执行需要加锁的逻辑
console.log('获取到锁,开始操作资源');
// 模拟资源操作耗时
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('资源操作完成,锁即将自动释放');
});
如果需要配置锁的模式,可以在第二个参数传入配置对象,比如设置为mode: 'shared'表示共享锁,多个任务可以同时获取共享锁,而默认的exclusive模式是独占锁,同一时间只能有一个任务获取:
// 申请共享锁
navigator.locks.request('test_lock', { mode: 'shared' }, async (lock) => {
console.log('获取到共享锁');
await new Promise(resolve => setTimeout(resolve, 1000));
});
Web Locks API的3种应用场景
场景一:多标签页共享数据同步
当多个浏览器标签页同时操作localStorage中的同一份共享数据时,很容易出现数据覆盖的问题。比如两个标签页同时读取localStorage中的计数器值,都加1后再写回,最终计数器只会加1而不是2。使用Web Locks API对localStorage的操作加锁就可以避免这个问题。
下面是多标签页计数器同步的示例代码:
// 多标签页安全的计数器自增方法
async function incrementCounter() {
// 对localStorage的counter资源加独占锁
await navigator.locks.request('local_storage_counter', async (lock) => {
// 读取当前计数器值
let current = parseInt(localStorage.getItem('counter') || '0');
// 模拟其他操作耗时
await new Promise(resolve => setTimeout(resolve, 500));
// 自增后写回
current += 1;
localStorage.setItem('counter', current.toString());
console.log('当前计数器值:', current);
});
}
// 调用方法
incrementCounter();
这样无论多少个标签页同时调用incrementCounter方法,都会按顺序获取锁执行操作,不会出现数据冲突。
场景二:异步任务队列控制
在一些需要按顺序执行异步任务的场景中,比如批量上传文件、按顺序调用接口,如果不做控制可能会出现任务并发执行导致的顺序混乱或者资源占用过高的问题。使用Web Locks API可以让异步任务按申请锁的顺序依次执行。
下面是异步任务队列控制的示例,确保三个任务按顺序执行:
// 任务队列的锁名称
const TASK_QUEUE_LOCK = 'async_task_queue';
// 定义三个异步任务
async function task1() {
await navigator.locks.request(TASK_QUEUE_LOCK, async (lock) => {
console.log('任务1开始执行');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('任务1执行完成');
});
}
async function task2() {
await navigator.locks.request(TASK_QUEUE_LOCK, async (lock) => {
console.log('任务2开始执行');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('任务2执行完成');
});
}
async function task3() {
await navigator.locks.request(TASK_QUEUE_LOCK, async (lock) => {
console.log('任务3开始执行');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('任务3执行完成');
});
}
// 同时触发三个任务,会按锁申请顺序依次执行
task1();
task2();
task3();
运行后会依次输出任务1、任务2、任务3的执行日志,不会出现并发执行的情况。
场景三:关键资源独占操作
有些操作需要独占资源,比如修改全局的配置状态、操作IndexedDB中的核心表,不希望被其他任务打断。这时候可以使用独占锁,确保操作过程中没有其他任务同时操作该资源。
下面是IndexedDB核心表操作的示例,对表操作加独占锁:
// 对IndexedDB核心表操作加锁
async function updateCoreTable(data) {
await navigator.locks.request('indexed_db_core_table', async (lock) => {
// 打开IndexedDB数据库
const request = indexedDB.open('my_db', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction('core_table', 'readwrite');
const store = transaction.objectStore('core_table');
// 执行更新操作
const updateRequest = store.put(data);
updateRequest.onsuccess = () => {
console.log('核心表更新完成');
};
};
});
}
// 调用更新方法
updateCoreTable({ id: 1, value: 'new_value' });
这样在更新核心表的过程中,其他申请同一把锁的任务会等待当前操作完成后再执行,保证核心资源操作的完整性。
注意事项
使用Web Locks API时需要注意,该API目前主流现代浏览器都已经支持,但是在一些旧版本浏览器中可能无法使用,使用前可以通过if ('locks' in navigator)判断浏览器是否支持。另外锁的作用范围是在同一个浏览器源下,不同源的页面无法共享锁。锁在页面卸载时会自动释放,不需要手动处理页面关闭的场景。
Web_Locks_APIjs资源锁web资源同步锁应用场景修改时间:2026-07-13 05:45:24