How to notify tabs with the same origin using Broadcast Channel
Tags: javascript, webdev
Published: 2024-02-19 19:54:32

Keeping track of the state of your objects in session and local storage ain't easy. 

I learned that on my own while developing a feature that allows the user, to add items in the application (which are kept on the client side) and manipulate them (edit/delete) before actually sending the whole bunch of items to an API or cancelling the entire operation, thus removing them from the session storage.

Everything worked fine and I was happy with how the data handling was done, right until I heard that there are users of this application that are duplicating their tabs: right clicking the browser's tab and then selecting "Duplicate".

Just to give a little bit of context here, if I have one opened tab and I have 3 elements in session storage, then I duplicate the tab, the second tab will also contain the same 3 elements that the first tab had in session storage. If user then adds a 4th element in the first tab, that will not be visible to the duplicated one(s) though.

So, what I needed here, in order to maintain the data consistency, was to notify the second tab (or any other duplicated tab), that the user cancelled the operation / sent the items to be processed by the API / closed the tab, so that all the other duplicated tabs could get reset as well (clear the session storage).

How could I achieve that? By using [BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API).

I created a BroadcastChannel in the javascript file of the page I needed 

```
const broadcastChannel = new BroadcastChannel('backloadingChannel');
const backloadingData = {
    message: "NotifyDuplicatedTabsWithSameSession",
    locationPathName: window.location.pathname
};
```
and I attached a listener to the "Cancel" / "Send to API" buttons so that when they get clicked, they post a message to the channel

```
if (document.getElementById('js-Save') != null) {
    document.getElementById('js-Save').addEventListener('click', function () {
        broadcastChannel.postMessage(backloadingData);
    });
}  
```
and, in the app.js I was listening to the messages received and I was clearing out the sessionStorage and reloaded the page whenever a user clicked on "Cancel" / "Send to API" (the reload is not mandatory, but in my case, I needed it - there was also some extra logic behind the scenes but this is the main reason I used BroadcastChannel).

```
const channel = new BroadcastChannel('backloadingChannel');

channel.onmessage = () => {
    if (sessionStorage.length > 0) {
            sessionStorage.clear();
            location.reload();
    }
};
```
Having this code in place allowed me to maintain state of objects across duplicated tabs and it was the easiest and cleanest way of doing it considering the project structure and the goal I wanted to achieve. 

As I said in this article, I also needed to maintain the state if the user closed the browser's tab. With more details about handling that, I will write a different article where I'll explain how I managed to differentiate between reloading and closing the tabs.

Until then, please let me know your thoughts on this. Have you ever needed to handle data in session storage using duplicated tabs? If yes, I would love to hear and learn from other's implementations.