Understanding the Web Locks API: Requesting, Monitoring, and Managing Locks in the Browser
This article introduces the Web Locks API, explaining how to request, monitor, and manage exclusive or shared locks across browser tabs and workers, covering optional parameters such as mode, ifAvailable, steal, and signal, with practical JavaScript code examples.
Domain
Scripts running in multiple browser tabs or workers can acquire a lock, perform work while holding the lock, and finally release it.
Requesting a Lock
Within the same origin, when a lock is held, other requests for the same lock are queued; the first queued request receives the lock only after it is released.
navigator.locks.request('mylock', {}, async (lock) => {
console.log(lock);
});The second argument of request is optional and can be used to pass additional options, which are described later.
Monitoring Locks
Querying the lock manager’s state is useful for debugging; it returns a snapshot that lists held locks and pending requests with details such as name, client_id, and mode.
navigator.locks.query().then((locks) => {
console.log(locks);
});Implementation Details
The following sections demonstrate how to use optional parameters of request to achieve various behaviours.
Returning a Value from an Asynchronous Task
The request() method itself returns a Promise that resolves once the lock is released.
const result = await navigator.locks.request('ccmama', {}, async (lock) => {
// task
return data;
});
console.log(result); // logs the data returned from the callbackShared and Exclusive Lock Modes
The mode option defaults to 'exclusive' ; 'shared' is also available.
A lock can have only one holder, but multiple shared locks can be granted simultaneously. In read‑write scenarios, 'shared' is used for reading, while 'exclusive' is used for writing.
navigator.locks.request('ccmama', {
mode: 'shared',
}, async (lock) => {
// task
});Conditional Acquisition
The ifAvailable option defaults to false . When set to true , the lock is granted only if it can be obtained immediately without queuing; otherwise null is returned.
navigator.locks.request('ccmama', { ifAvailable: true }, async lock => {
if (!lock) return;
// task
});Emergency "Steal" to Prevent Deadlocks
The steal option defaults to false . When true , any existing lock with the same name is released and the request is granted, pre‑empting queued requests.
navigator.locks.request('ccmama', { steal: true }, async lock => {
// task
});⚠️ Use with caution. Code that was running inside the previous lock will continue to run and may conflict with the new holder.
Aborting a Lock Request
The signal option accepts an AbortSignal . If the associated AbortController aborts, the lock request is discarded.
try {
const controller = new AbortController();
setTimeout(() => controller.abort(), 400);
navigator.locks.request('ccmama', { signal: controller.signal }, async lock => {
// task
});
} catch (ex) {}
// Or using AbortSignal.timeout
try {
navigator.locks.request('ccmama', { signal: AbortSignal.timeout(1000) }, async lock => {
// task
});
} catch (ex) {}⚠️ A timeout throws an exception that must be caught with try/catch .
Reference Articles
MDN Web Locks API documentation
Personal notes on Web Locks
Discussion about the steal option
Web Locks API: Cross‑Tab Resource Synchronization
Read‑Write Locks
Feel free to discuss if any part is unclear.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.