Use-case:

let´s say , we want to share some informations (for example, an authentication token) between browser tabs which would suggest to use HTML5 localStorage. But we don’t want anything related to authentication to stay in my storage when the browser is closed which would suggest using HTML5 sessionStorage.

The first alternative would be to use cookies , because the cookies meet all the above requirements.

  • Cookies are shared across all same origin tab. You can even specify their paths, but they are shared by default.
  • Cookies are automatically deleted by browser when it is closed, you need to do nothing; this is again the default behaviour.
  • Cookies can be easily made as secure or more secure than storage.

But, there is some problem with this solution.Cookies are sent with every request, so they can worsen performance (especially for mobile data connections). At that time, we will not use it yet.

another option to achieve this, could be to clean the localStorage when the page is about to be closed/unloaded, so nothing stays behind in storage. That way the localStorage would behave like the sessionStorage in the sense that it would be removed once the page is closed, but it would still have the advantage from the localStorage of sharing data across tabs.

For that we could use the onbeforeunload event:

The beforeunload event is fired when the window, the document and its resources are about to be unloaded.

Something like this:

// when the page is about to be unloaded, remove the localStorage data
window.addEventListener("beforeunload", function() {
    //our method here
});

Let´s translate it in Angular :

@HostListener('window:beforeunload') onBeforeUnload() {
   // our method here
  }

One option to achieve this could be to clean the localStorage when the page is about to be closed/unloaded, so nothing stays behind in storage. That way the localStorage would behave like the sessionStorage in the sense that it would be removed once the page is closed, but it would still have the advantage from the localStorage of sharing data across tabs.

For that we could use the onbeforeunload event:

The beforeunload event is fired when the window, the document and its resources are about to be unloaded.

Something like this:

// code here
...

// you have the data in the localStorage
localStorage.setItem("data", "My Data");

// more code here
...

// when the page is about to be unloaded, remove the localStorage data
window.addEventListener("beforeunload", function() {
    localStorage.removeItem("data");
});

That is a good start for solving our issue. But that solution is way too simple, and there is a catch: when you close one tab, the localStorage data is deleted, even if you have other tabs open! (leaving them without any data). To prevent removing the data when one of the tabs is closed, you could keep track of the number of tabs, and only clean the localStorage when the number is zero.

The pseudo-code for that would be:

  1. On page load:
    1. If the localStorage has a count of tabs
      1. Increment the tab count by 1
    2. Or else (no count of tabs)
      1. Create a variable in the localStorage that will contain the number of tabs.
      2. Set that variable to 1 (the current tab).
  2. On page unload:
    1. Decrease the tab count by 1.
    2. If the tab count is zero (this was the last tab open)
      1. Delete the content of the localStorage

Troubleshooting

This could be a nice start solution, but we still have one painful caveat:

If the user only has one tab open and they refresh the page, the storage gets cleared.

 We will go around that issue by copying the value of localStorage.data to sessionStorage.data right before removing it from the localStorage, then on load if there are no tabs, check if sessionStorage.data exists and initialize it to that value. The sessionStorage will be preserved in a refresh but not on a window/tab close.

Final Code in Javascript.

<script>
            window.addEventListener("load", function() {
                if (!localStorage.tabs) {
                    //Create the tab count
                    localStorage.setItem("tabs", 1);
                    // restore data in case of refresh, or set to initial value in case of new window
                    localStorage.setItem("data", sessionStorage.getItem("data") || "Initial");
                } else {
                    //Add one tab to the count
                    localStorage.tabs++;
                }
            });

            window.addEventListener("beforeunload", function() {
                if (parseInt(localStorage.tabs) == 1) {
                     //Last tab, so we can remove localStorage"
                    // but first we save the data temporarily in the sessionStorage (in case of reload)
                    sessionStorage.setItem("data", localStorage.getItem("data")); 
                    localStorage.removeItem("tabs");
                    localStorage.removeItem("data");
                } else {
                  //There are more tabs open, decrease count by 1"
                    localStorage.tabs--;
                }
            });
        </script>

next opened issues : For browsers or tabs crashing, the above code doesn´t work well. As result, we will end up with uncleaned or invalid count in storage.

A solution could be the use of a timestamp checker : the data would still be in the localStorage but it would be deleted on load if it has been more than x time since the last update

By Shabazz

Software Engineer, MCSD, Web developer & Angular specialist

Leave a Reply

Your email address will not be published. Required fields are marked *