15

Is there any way for two tabs within a browser to share a Mutex (in JavaScript)?

I am working on a web-app using node.js & socket.io, and I want the various tabs to share a single connection with the server. The so-called 'leader' tab is the only one that maintains the connection, while messages to the rest of them are all relayed via this one. Right now, I'm using a leader election algorithm to choose the leader, but given that it takes a second or two to re-elect a new leader if the current one goes down, I wonder if there is a better method to do the same.

Kaustubh Karkare
  • 1,083
  • 9
  • 25
  • You might also want to take a look at [SharedWorker](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker), which is a convenient way to share this sort of work between n different tabs. SharedWorker also disqualifies you from [bfcache](https://web.dev/bfcache/) though – a cat Jul 30 '22 at 11:52

2 Answers2

6

This has essentially been added to browsers, and it's called the Web Locks API.

A leader election is as simple as acquiring an exclusive lock of a given name, then holding it however long you wish.

let abdicate; // function that releases the lock

navigator.locks.request("takemetoyourleader", lock => {
    console.log("wow I just won the election");

    return new Promise(resolve => {
        abdicate = resolve;
    });
});

By returning a Promise that doesn't resolve, the lock is held indefinitely. When the tab holding the lock is closed, the lock will automatically be released, and a different tab of the same origin can obtain it instead.

Note that holding a lock will disqualify your site from using the bfcache, so you might want to implement pagehide/pageshow listeners to manually release/retake this lock.

a cat
  • 654
  • 1
  • 10
  • 17
2

There are various libraries that either try to solve the problem of locking directly or provide message passing between tabs, which you could use as a building block. Check out:

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149
qbolec
  • 5,374
  • 2
  • 35
  • 44