📜 ⬆️ ⬇️

Communication scripts from different browser tabs

I wanted to communicate 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 cannot be seen . But there is a cross-browser alternative that few people know about. Let's figure it out.

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

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

Did you know that localStorage triggers events? More precisely, an event occurs when something is added, changed or removed 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 the change
url - URL of the page where the change occurred

Therefore, you can establish communication between the tabs by simply setting values ​​in localStorage. Provide the following example (pseudocode):

 var loggedOn; // TODO:      logonChanged(); window.addEventListener('storage', updateLogon); window.addEventListener('focus', checkLogon); function getUsernameOrNull () { // TODO: ,    } function logonChanged () { var uname = getUsernameOrNull(); loggedOn = uname; localStorage.setItem('logged-on', uname); } function updateLogon (event) { if (event.key === 'logged-on') { loggedOn = event.newValue; } } function checkLogon () { var uname = getUsernameOrNull(); if (uname !== loggedOn) { location.reload(); } } 


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

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

API easier


The localStorage API is one of the easiest interfaces. However, it also has a peculiarity - for example, Safari and QuotaExceededError, there is no support for JSON and old browsers.

For this, I made a module that provides local storage with a simplified API, relieves you of these features, works with memory, if suddenly there is no support for localStorage, and makes it easier to work with events. You can register and delete listeners of these events for specified keys.

Here is a scheme for working with local-storage .

ls (key, value?) gets or sets the key value
ls.get (key) gets key value
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 event handler and keeps track of all the keys you are monitoring, instead of registering a lot of events.

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

Source: https://habr.com/ru/post/250891/


All Articles