Communication scripts from different browser tabs

Original author: Nicolas Bevacqua
  • Transfer
I wanted to establish communication scripts from different browser tabs. The future SharedWorker API allows you to transfer data between different iframes and even tabs or windows. In Chrome, it has been working for a long time, in Firefox - recently, but in IE and Safari it is not visible . But there is a cross-browser alternative that few people know about. Let's get it right.

Imagine that on one tab a person logged in, then opened another, and logged out there. At the first, it seems to be logged in, but when he does something there, they will give him an error. It would be nice to at least show him a dialogue that he had logged out and that he needed to enter again.

It would be possible to use the WebSocket API, but it is too complicated. I started looking for other solutions. The first is to save cookies and localStorage, and check them periodically. But this would burden the processor with a rather useless task - after all, the output might not have happened at all. I would be more comfortable with options with long-polling (long requests), Server-Sent Events or WebSockets. Surprisingly, it turned out that the answer lay in the localStorage area!

Do you know that localStorage fire events? More precisely, an event occurs when something is added, changed or deleted from the repository. This means that when you touch localStorage in any tab, everyone else can find out about it. Just listen to the events in the window object.

window.addEventListener('storage', function (event) {
  console.log(event.key, event.newValue);
});


The event object has the following properties:

key - the key that was touched in localStorage
newValue - the new value assigned to it
oldValue - the value before changing the
url - URL of the page on which the change occurred

Therefore, you can establish communication between the tabs by simply setting the values ​​in localStorage. Imagine the following example (pseudo-code):

var loggedOn;
// TODO: когда пользователь меняется или выходит
logonChanged();
window.addEventListener('storage', updateLogon);
window.addEventListener('focus', checkLogon);
functiongetUsernameOrNull () {
  // TODO: возврат, когда пользователь входит
}
functionlogonChanged () {
  var uname = getUsernameOrNull();
  loggedOn = uname;
  localStorage.setItem('logged-on', uname);
}
functionupdateLogon (event) {
  if (event.key === 'logged-on') {
    loggedOn = event.newValue;
  }
}
functioncheckLogon () {
  var uname = getUsernameOrNull();
  if (uname !== loggedOn) {
    location.reload();
  }
}


When the user goes to one of the tabs and goes to the other, the page reloads and the server logic redirects it somewhere. In this case, the check occurs only if the user has selected this tab. If suddenly he went out and went in on one of the tabs, there is no need to log it out on everyone else.

This should work the other way - if the user logged in on one tab, and he was logged into the other, then when you switch to the second tab, the page will reload and it will also be logged in there. Joy.

API is simpler


localStorage API is one of the simplest interfaces. However, it also has a feature - for example, Safari and QuotaExceededError, there is no support for JSON and older browsers.

To do this, I made a module that provides local storage with a simplified API, saving you from these features, working with memory, if suddenly there is no localStorage support, and making it easier to work with events. You can register and delete listeners for these events for specified keys.

Here is the scheme of working with local-storage .

ls (key, value?) gets or sets the value of the key
ls.get (key) gets the value of the key
ls.set (key, value) sets the value
ls.remove (key) removes the key
ls.on (key, fn (value, old, url)) listens for changes in other tabs, starts fn
ls.off (key, fn) removes the listener that was registered through ls.on

It is worth mentioning that local-storage registers one an event handler and keeps track of all the keys that you are observing, instead of registering many events.

Perhaps you can come up with other cases where it is possible to use communication between tabs. So far, SharedWorker has not received proper distribution, and the WebSockets approach is unreliable if your application focuses primarily on working offline.

Also popular now: