Until the Web Locks API is universally available, a ServiceWorker is probably the best cross-platform mechanism for locking among contexts with the same origin. This is a proof-of-concept implementation of locking using a ServiceWorker.
See the ServiceWorker code and how it is invoked from a client (this would likely be abstracted into a library).
Locking requests are made from a client to the ServiceWorker using fetch
with a special HTTP header providing the JSON request. The ServiceWorker holds the fetch request until it can be satisfied. A browser can stop the ServiceWorker at any time, including during an ongoing fetch, so clients must retry a request if rejected.
The global state of a ServiceWorker is reset whenever it is restarted, so lock state is persisted to IndexedDB.
Orphaned locks are detected by comparing the clientId of a lock holder to the active clients obtained by Clients.matchAll
.
Each box on the demo page is an iframe context. New iframes can be added and existing ones removed.
Within each context you can request a shared or exclusive lock, or release an acquired lock. When a lock is requested, its type is highlighted in yellow while pending and in green once acquired.
If a context is removed while holding a lock, it will eventually be released for the next requester. This may take a few seconds.