Vaadin JavaScript 卸载事件侦听器未触发

Vaadin JavaScript unload event listener not firing

我有一个 Vaadin 7 应用程序,我需要在其中可靠地检测用户离开或离开页面以执行一些清理工作。

我的目标是让页面在 browser/tab 关闭时弹出一个确认对话框,如果用户选择离开页面,那么我会在那时执行清理操作。

我在 JavaScript 方面相当缺乏经验,但根据我的发现,'onbeforeunload' 和 'onunload' 是可以使用的函数。

此时,我在进入页面时使用以下代码:

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};"       
);

然后,当我点击我界面上的"Start"按钮开始运行时:

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

当我离开我的网页时,例如通过关闭选项卡,我会收到一个确认弹出窗口,就像我想要的那样。但是,如果我单击“是”,页面将关闭,但我的 'unload' 事件不会触发。当我单击相应的 "Stop" 按钮时,清理工作正常,所以我知道那部分没问题。

据我所知,主流浏览器都支持 onunload(我试过 Firefox、Chrome、Safari 和 Opera)。更有趣的是,如果我使用以下代码,那么我的 closeListener 会在 'beforeunload' 侦听器上触发,但不会在 'unload' 侦听器上触发:

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

所以我的问题是,'unload' 侦听器不触发的原因可能是什么? 这种方法是执行清理操作的好方法吗? ?

注意:下面是我在网页关闭时进行清理操作的回调函数,以防对 'unload' 侦听器产生任何影响。我根本没有打印出来,所以这意味着 "catchClose" 函数没有被调用。

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

编辑:通过进一步调查,实际上似乎 unload 方法偶尔会正确触发,但我无法确定它何时以及为何会触发。此外,我发现如果我在我的 "closeListener" 函数中放置一个断点,它会被调用,并且我的卸载工作绝对正常。

编辑:对我来说,代码现在似乎适用于 Safari、Firefox 和 Opera,但不适用于 Chrome。我怀疑这是由于 的副作用,我现在已经解决了。

我找到了解决问题的方法。

我怀疑这个问题的大部分已通过 的解决方案解决,该解决方案涉及将代码的某些部分放入同步方法中。解决此问题后,卸载方法适用于我测试过的大多数浏览器。但是,Chrome 仍在播放,只会在浏览器关闭时触发卸载事件,而不是在选项卡关闭时触发。添加 'pagehide' 监听器似乎意味着 Chrome 选项卡关闭现在可以正常运行。

因此,'unload' 和 'pagehide' 事件的组合似乎适用于所有浏览器,并且(对我而言)似乎是可靠,我的清理总是在用户离开页面时执行。