javascriptaddeventlistenervaadin7onbeforeunloadonunload

Vaadin JavaScript unload event listener not firing


I have a Vaadin 7 application where I need to reliably detect a user leaving or navigating away from a page in order to carry out some cleanup.

My aim is to have the page pop up a confirmation dialog on browser/tab close, and if the user chooses to leave the page, then at that point I perform the cleanup operation.

I am fairly inexperienced at JavaScript, but from what I have discovered 'onbeforeunload' and 'onunload' are the functions to use.

At this point in time, I am using the following code when I enter the page:

JavaScript.getCurrent().execute(
    "beforeCloseListenerGlobal = function beforeCloseListener (e) {\nvar e = e || window.event;\nvar message = " + LEAVE_PAGE_MESSAGE + ";\nif(e) e.returnValue = message;\nreturn message;\n};\n" +
    "closeListenerGlobal = function closeListener () {\ncatchClose();\n};\n" +
    "addCloseListenersGlobal = function addCloseListeners () {\nwindow.addEventListener('beforeunload', beforeCloseListenerGlobal);\nwindow.addEventListener('unload', closeListenerGlobal);\n};\n" +
    "removeCloseListenersGlobal = function removeCloseListeners () {\nwindow.removeEventListener('beforeunload', beforeCloseListenerGlobal);\nwindow.removeEventListener('unload', closeListenerGlobal);\n};"       
);

Then, when I click the "Start" button on my interface to start the operation:

JavaScript.getCurrent().execute("addCloseListenersGlobal();");

When I navigate away from my webpage, by closing the tab for example, I get a confirmation pop-up, just as I want. However, if I click Yes, the page closes but my 'unload' event does not fire. When I click the respective "Stop" button, the cleanup works correctly, so I know that part is fine.

From what I've read the major browsers all support onunload (I've tried Firefox, Chrome, Safari and Opera). More interestingly, if I use the following code, then my closeListener fires on the 'beforeunload' listener, but not on the 'unload' listener:

JavaScript.getCurrent().execute(
    "function closeListener() { catchClose(); } " +
    "window.addEventListener('beforeunload', closeListener); " +
    "window.addEventListener('unload', closeListener);"
);

So my question is, what could be the reason for the 'unload' listener not to fire? Is this method a good and reliable way to perform a cleanup operation?

Note: below is my function callback for the cleanup operation on webpage close, in case that would have any effect on the 'unload' listener. I do not get a print out at all, so that implies the "catchClose" function is not called.

JavaScript.getCurrent().addFunction("catchClose", arguments -> {
    System.out.println("catchClose callback from " + Page.getCurrent().getWebBrowser().getBrowserApplication());
    presenter.webPageClosed();
});

Edit: Through further investigation it actually appears as though the unload method very occasionally does fire correctly, though I cannot pinpoint when and why it does that just yet. Also, I have discovered that if I put a breakpoint inside my "closeListener" function, it gets called, and my unload works absolutely fine.

Edit: For me it now appears as if the code works for Safari, Firefox and Opera, but not Chrome. I suspect it is due to a side effect from my related question which I have now resolved.


Solution

  • I have found the solution to my problem.

    I suspect that most of this issue was solved by the solution to my other related issue which involved putting certain parts of code into synchronous methods. After fixing this issue, the unload method worked across most of the browsers I have tested on. However, Chrome was still playing up and would only fire the unload event on browser close, and not on tab close. Adding in a 'pagehide' listener seems to mean that Chrome tab closing is now acting appropriately.

    So, a combination of 'unload' and 'pagehide' events seems to work across all browsers, and (as of now for me) appears to be reliable, and my cleanup is always performed when the user leaves the page.