我有一个要求,如果它空闲一段时间,我必须注销用户。我正在使用 ng-idle 0.3.2。
如果浏览器中打开了多个选项卡/窗口,我会遇到问题。如果我正在处理一个选项卡并且未激活的选项卡将被注销,而我正在处理的活动选项卡仍处于登录状态,因为它处于活动状态。
当我在另一个类似的选项卡上工作时,如何防止从非活动选项卡注销?
使用 localStorage 在运行您的应用程序的任何选项卡中存储最后一个已知活动事件的时间戳。在您正在运行的应用程序的每个实例中每隔几秒轮询一次该值。如果已更新,请重置 ng-idle 计时器以避免过早注销(或在广播 $idleTimeout 事件时设置的任何操作)。
创建一个指令来体现上述行为:
.directive('idle', function($idle, $timeout, $interval){
return {
restrict: 'A',
link: function(scope, elem, attrs) {
var timeout;
var timestamp = localStorage.lastEventTime;
// Watch for the events set in ng-idle's options
// If any of them fire (considering 500ms debounce), update localStorage.lastEventTime with a current timestamp
elem.on($idle._options().events, function(){
if (timeout) { $timeout.cancel(timeout); }
timeout = $timeout(function(){
localStorage.setItem('lastEventTime', new Date().getTime());
}, 500);
});
// Every 5s, poll localStorage.lastEventTime to see if its value is greater than the timestamp set for the last known event
// If it is, reset the ng-idle timer and update the last known event timestamp to the value found in localStorage
$interval(function() {
if (localStorage.lastEventTime > timestamp) {
$idle.watch();
timestamp = localStorage.lastEventTime;
}
}, 5000);
}
}
})
将指令属性添加到 body 标记以确保检测到页面内的所有鼠标和键盘事件:
<body ng-app="myApp" idle>
在多个选项卡中打开并运行此 Plunk,每个选项卡都有一个控制台。将鼠标光标移到正文内容上并观察记录到两个控制台的事件。
我还没有使用过 ngIdle,但通常在这些情况下你需要与服务器通信。即在 $keepalive 事件中,向服务器发送请求以存储会话中的最后活动时间。在 $idleWarn 中,向服务器发送请求以获取最新的活动时间戳,如果用户在其他选项卡中处于活动状态,那么您将获得最近的时间戳,因此您可以停止超时过程并发送保活。