2

From my (poor) understanding of the Web Storage, the sessionStorage object is maintained per-tab, it survives page reloads and page navigation, and it gets destroyed on tab close or browser process termination.

Is there a way to listen to the sessionStorage destroy event?
I need to perform an HTTP call when the tab or window is being closed and it seems the sessionStorage is the single object which follow a similar lifecycle.

LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • You might just listen for the `unload` event – CertainPerformance Apr 26 '19 at 08:49
  • 3
    @CertainPerformance the problem is it seems `unload` is triggered on page-reload and navigation. Or am I wrong? – LppEdd Apr 26 '19 at 08:50
  • *"I need to perform an action"* What action do you want to perform? – NewToJS Apr 26 '19 at 08:52
  • @NewToJS I need to perform an HTTP call. I'm open to any solution. – LppEdd Apr 26 '19 at 08:53
  • _the sessionStorage object is maintained per-tab.._ AFAIK `sessionStorage` is per-origin, i.e. specific to URL, not tab. – hindmost Apr 26 '19 at 08:55
  • 1
    Yep, that makes sense, so you want a way to differentiate closing from navigating/reloading, but for what you're looking for, it might not be possible. Closest I found was https://stackoverflow.com/questions/568977/identifying-between-refresh-and-close-browser-actions - inelegant, but maybe send out the network request regardless, and on pageload, if sessionStorage exists, send out another request saying to ignore what was just sent. (have the server process whatever you're doing only after 10 seconds, or something like that, to give the page time to reload/navigate) – CertainPerformance Apr 26 '19 at 08:56
  • 2
    @hindmost I think OP is right. From the documentation : `Opening a page in a new tab or window will cause a new session to be initiated with the value of the top-level browsing context`. I might not understand it correctly, so please correct me if I'm wrong. – Seblor Apr 26 '19 at 08:57
  • 1
    @hindmost - `sessionStorage` is page-based, see https://www.w3.org/TR/webstorage/#the-sessionstorage-attribute. (*Also* origin-based, but opening two pages from the same origin gives you two separate session stores.) – T.J. Crowder Apr 26 '19 at 09:00
  • Thanks everyone. It seems there is not a standard / non-hackish way to do this. That's a pity. – LppEdd Apr 26 '19 at 09:02
  • 1
    Well, there is a way, but that is by WebSocket @LppEdd and it's pretty much what you want. – weegee Apr 26 '19 at 09:03
  • @window.document oh I think I have no problem initiating a WebSocket connection. So basically I'd have to listen to a "disconnect" event directly on the server side? I'm on a Java/Spring backend, but I think this is a universal behavior. – LppEdd Apr 26 '19 at 09:05
  • No! use socket.io and listen to the **disconnecting** event. Like a chat, when the user closes the browser or deletes the session, then the event is fired, the difference is that we can have the socket_Id of the user on the disconnecting event while they are disconnecting – weegee Apr 26 '19 at 09:07
  • 1
    Wouldn't a websocket be closed on a page refresh ? – Seblor Apr 26 '19 at 09:08

1 Answers1

3

Is there a way to listen to the sessionStorage destroy event?

No, there is no "destroy" event for session storage.

I need to perform an HTTP call when the tab or window is being closed and it seems the sessionStorage is the single object which follow a similar lifecycle.

You can't differentiate between page reload and navigating away from the page.

The only thing I can think of to get close to what you want to do is to do this:

  1. In beforeunload or unload, use sendBeacon to do your HTTP call (it has to be a POST). You can't just use standard ajax (XMLHttpRequest/fetch), browsers are actively disabling standard ajax in unload events. So use sendBeacon if it's there, falling back to a standard (and — ugh! — synchronous) ajax request if it isn't (as that suggests and older browser were it may still work).
  2. On page load, check sessionStorage for a marker and:
    • If it's there, do an ajax call basically saying "never mind!" to say that if the server just received an "I'm leaving the page" ajax call, it should disregard it.
    • If it's not there, set the marker.

You'll need to be sure that the server handles the possibility that, because of the vagaries of network requests (particularly as beacons are always asynchronous), the two requests may be received by the server out of order. So include some serialization information in them (for instance, a value from performance.now(), falling back to Date.now() if necessary).

Or, of course, use polling when the page is open and a timeout to indicate the user has left the page. The tradeoffs between the approaches will be fun to weigh. :-)


The user window.document (interesting username!) points out that you may be able to use web sockets for this. I don't have much experience using web sockets (must fix that!) but I think the general idea is that you'll see a socket disconnect when the user leaves the page or refreshes, but (like the above) if it's a refresh, you'll see a socket connection again very soon thereafter — which is like the "never mind!" call above.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    I'll have to discuss about this with the team, but it seems the first proposed solution is the better one. Uhhh, why I decided to do front-end... – LppEdd Apr 26 '19 at 09:15
  • The best solution instead of using web sockets. btw, a silly question is there a chance of MiM attack with the sendBeacon? Be it any secure information, the op is trying to transfer – weegee Apr 26 '19 at 09:16
  • 1
    @window.document - No more so than any other ajax call. :-) – T.J. Crowder Apr 26 '19 at 09:17