使用OnBeforeUnload事件刷新浏览器

时间:2014-10-27 14:42:22

标签: javascript mongodb session angularjs-scope browser-close

在用户点击注销按钮的网页上,我有一个JavaScript函数,用于清除存储在MongoDB上的用户会话。它工作正常。

此外,我想在用户关闭浏览器时清除用户会话。这是我面临的问题:当用户点击刷新图标时,将调用注销功能。我只希望在浏览器关闭时调用此函数。

我可以阻止此功能调用页面刷新吗?

我的逻辑是在浏览器关闭时清理会话。我正在删除MongoDB上的会话。有没有更好的方法来管理会话?

var isRefresh = false;
$(window).keydown(function (event) {
    if (event.keyCode == 116) { // User presses F5 to refresh
        refresh = true;
    }
});

// Calls the logout function when you close the browser thus cleans the session data.
var windowsCloseEventListener = window.attachEvent || window.addEventListener;
var chkForBrowserCloseEvents = window.attachEvent ? 'onbeforeunload' : 'beforeunload'; /// make IE7, IE8 compitable
windowsCloseEventListener(chkForBrowserCloseEvents, function (e) { // For >=IE7, Chrome, Firefox
    if (!isRefresh) {
        $scope.logout();
    }
});

6 个答案:

答案 0 :(得分:2)

据我所知,您实际上无法测试浏览器是否已关闭;您只能测试关闭的窗口(或标签)。这通常就足够了,除非页面刷新当然发生,因为它算作关闭和重新打开窗口或标签内的网页。我们需要的是点击浏览器页面刷新按钮的事件处理程序,但我不确定是否存在。这是:

How to show the "Are you sure you want to navigate away from this page?" when changes committed?

以及

Handling Browser close event and Page Refresh

我在尝试查找页面刷新事件处理程序时遇到的一件事是使用“本地存储”的概念。作为on-before-unload处理程序的一部分,您可以将带有时间戳的小数据项放入本地存储中。在服务器上激活一种计时器,并等待该时间到期,然后再擦除会话。加载页面后,测试该数据项的本地存储。如果它存在并且时间戳是最近的,你知道页面被刷新并且可以基于知道 - 例如向服务器发送AJAX消息告诉它还没有擦除会话来做适当的事情。

答案 1 :(得分:2)

为了更好地管理会话并解决用户按下浏览器刷新问题,您需要

  • 关闭窗口时删除注销功能。
  • 在客户端和服务器上实施InActivity监视器,如果用户在特定时间内处于非活动状态,则会清除会话。因此,如果用户关闭浏览器,MongoDB中的会话将持续一段时间,直到服务器清除它。
  • 从客户端到服务器实施keepalive ping,如果用户在页面上处于活动状态,则服务器将每隔设定的时间间隔对服务器执行ping操作。为了减少网络流量,只要使用AJAX或RESTful api调用服务器,就可以重新安排keepalive。
  • 将用户会话保存在浏览器的本地存储中,以便在浏览器刷新时重新读取会话。

此InActivity监视器可以作为一个很好的起点。 https://github.com/HackedByChinese/ng-idle/blob/develop/src/angular-idle.js。我在我的角度项目中做了以上所有事情。希望有所帮助。

答案 2 :(得分:2)

正如亚历克斯建议的那样,您可以使用会话Cookie 来检查您的网站是否已在当前会话中看到过(IE7 +支持)。

示例

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

var isRefresh = true;
var sessionAlive = readCookie("sessionAlive");
if (sessionAlive === null) {
    isRefresh = false;
    sessionStorage.setItem("sessionAlive", true);
}

var windowsCloseEventListener = window.attachEvent || window.addEventListener;
var chkForBrowserCloseEvents = window.attachEvent ? 'onbeforeunload' : 'beforeunload';
windowsCloseEventListener(chkForBrowserCloseEvents, function (e) {
    if (!isRefresh) {
        $scope.logout();
    }
});

您可以使用 sessionStorage (更多HTML5方式)来查看浏览器是否已关闭(新会话)(IE8 +支持)。

示例:

var isRefresh = true;
var sessionAlive = sessionStorage.getItem("sessionAlive");
if (sessionAlive === null) {
    isRefresh = false;
    sessionStorage.setItem("sessionAlive", true);
}

var windowsCloseEventListener = window.attachEvent || window.addEventListener;
var chkForBrowserCloseEvents = window.attachEvent ? 'onbeforeunload' : 'beforeunload';
windowsCloseEventListener(chkForBrowserCloseEvents, function (e) {
    if (!isRefresh) {
        $scope.logout();
    }
});

readCookie来自:http://www.quirksmode.org/js/cookies.html

答案 3 :(得分:1)

使用会话过期的cookie应该有效。

答案 4 :(得分:0)

WindowEventHandlers.onbeforeunload

window.onbeforeunload = function(e) {
  return 'Dialog text here.';
};

此示例显示addEventListener和attachEvent方法不能用于onbeforeunload事件(Google Chrome和Safari除外):

 if (window.addEventListener) {  // all browsers except IE before version 9
            window.addEventListener ("beforeunload", OnBeforeUnLoad, false);
        }
        else {
            if (window.attachEvent) {   // IE before version 9
                window.attachEvent ("onbeforeunload", OnBeforeUnLoad);
            }
        }

            // the OnBeforeUnLoad method will only be called in Google Chrome and Safari
        function OnBeforeUnLoad () {
            return "All data that you have entered will be lost!";
        }

答案 5 :(得分:0)

你可以使用&#34; onbeforeunload&#34;处理这种情况的事件。

$wnd.onbeforeunload = function(e) {

        var logoutClicked = callSomeFunctionToGetIfLogoutButtonIsClicked();
        if (!logoutClicked) {
            return "Some message";
        }
        return;
    }