【问题标题】:Browser refresh using OnBeforeUnload event使用 OnBeforeUnload 事件刷新浏览器
【发布时间】:2014-12-22 18:44:37
【问题描述】:

在用户单击注销按钮时的网页上,我有一个 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();
    }
});

【问题讨论】:

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


    【解决方案1】:

    正如 Alex 所建议的,您可以使用 session Cookies 来检查您的网站是否在当前会话中被看到(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

    【讨论】:

      【解决方案2】:

      您可以使用“onbeforeunload”事件来处理这种情况。

      $wnd.onbeforeunload = function(e) {
      
              var logoutClicked = callSomeFunctionToGetIfLogoutButtonIsClicked();
              if (!logoutClicked) {
                  return "Some message";
              }
              return;
          }
      

      【讨论】:

        【解决方案3】:

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

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

        这个 InActivity 监视器是一个很好的起点。 https://github.com/HackedByChinese/ng-idle/blob/develop/src/angular-idle.js。我已经在我的 Angular 项目中完成了上述所有工作。希望对您有所帮助。

        【讨论】:

        • 非常感谢,我会看看你的解决方案。
        【解决方案4】:

        使用带有会话过期的 cookie 应该可以工作。

        【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          据我所知,您实际上无法测试浏览器是否被关闭;您只能测试正在关闭的窗口(或选项卡)。这通常就足够了,除非当然发生页面刷新,因为它既可以关闭又可以重新打开窗口或选项卡内的网页。需要的是一个事件处理程序,用于单击浏览器的页面刷新按钮,但我不确定是否存在。这里有一些东西:

          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 消息,告诉它暂时不要删除会话。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-11-15
            • 2019-12-03
            • 2018-09-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多