是否有可能在JavaScript中检测“空闲”时间?
我的主要用例可能是预取或预加载内容。
我将空闲时间定义为用户不活动或没有任何CPU使用的时间段
是否有可能在JavaScript中检测“空闲”时间?
我的主要用例可能是预取或预加载内容。
我将空闲时间定义为用户不活动或没有任何CPU使用的时间段
当前回答
下面是一个在Angular中完成的AngularJS服务。
/* Tracks now long a user has been idle. secondsIdle can be polled
at any time to know how long user has been idle. */
fuelServices.factory('idleChecker',['$interval', function($interval){
var self = {
secondsIdle: 0,
init: function(){
$(document).mousemove(function (e) {
self.secondsIdle = 0;
});
$(document).keypress(function (e) {
self.secondsIdle = 0;
});
$interval(function(){
self.secondsIdle += 1;
}, 1000)
}
}
return self;
}]);
请记住,这个空闲检查器将为所有路由运行,因此应该在angular应用程序加载时在.run()中初始化它。然后你可以使用idleChecker。在每个路由内的secondside。
myApp.run(['idleChecker',function(idleChecker){
idleChecker.init();
}]);
其他回答
尝试freddoo的解决方案,但它在1分钟超时时间内不起作用,所以我稍微改变了它,以记录用户最后一次点击页面的日期+时间,在我的timerIncrement函数中,我计算当前时间和最后一次点击时间之间的差异,如果该值恰好大于或等于超时值,那么我重定向:
var clickedDate = new Date();
var idleTime = 1; //
function timerIncrement() {
var nowDate = new Date();
var diffMs = (nowDate - clickedDate); //Milliseconds between now & the last time a user clicked somewhere on the page
var diffMins = Math.round(((diffMs % 86400000) % 3600000) / 60000); //Convert ms to minutes
if (diffMins >= idleTime) {
//Redirect user to home page etc...
}
}
$(document).ready(function () {
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
$(this).click(function (e) {
clickedDate = new Date();
});
});
就像它可以得到的那样简单,检测鼠标移动的时间:
var idle = false;
document.querySelector('body').addEventListener('mousemove', function(e) {
if(idle!=false)
idle = false;
});
var idleI = setInterval(function()
{
if(idle == 'inactive')
{
return;
}
if(idle == true)
{
idleFunction();
idle = 'inactive';
return;
}
idle = true;
}, 30000); // half the expected time. Idle will trigger after 60 s in this case.
function idleFuntion()
{
console.log('user is idle');
}
您要求优雅,我创建了一个简单的类来支持惰性检查(具有空闲状态),除了命令方式(带有回调)之外。此外,当违反空闲时间时,该类支持“backToActive”。
class Idle {
constructor(timeout = 10, idleCallback = null, backToActiveCallback = null, autoStart = true, backToActiveOnXHR = false) {
this.timeout = timeout
this.idleCallback = idleCallback
this.backToActiveCallback = backToActiveCallback
this.autoStart = autoStart // only F5
this.backToActiveOnXHR = backToActiveOnXHR
this.idle = false
this.timer = null
this.events = ['scroll', 'mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart']
this.init()
}
init() {
if(this.backToActiveOnXHR) {
this.events.push('load')
}
this.events.forEach(name => {
window.addEventListener(name, this.backToActive, true)
})
if(this.autoStart) {
this.backToActive()
}
}
goIdle = () => {
this.idle = true
if(!!this.idleCallback) {
this.idleCallback(this.timeout)
}
}
backToActive = () => {
if(this.idle) {
this.backToActiveCallback()
}
this.idle = false
clearTimeout(this.timer)
this.timer = setTimeout(this.goIdle, this.timeout * 1000)
}
}
用法:
let idleCallback = timeout => { console.log(`Went idle after ${timeout} seconds`) }
let backToActiveCallback = () => { console.log('Back to active') }
let idle = new Idle(30, idleCallback, backToActiveCallback)
devtools的结果:
// Went idle after 30 seconds <--- goes idle when no activity is detected
// Back to active <--- when the user is detected again
支持懒惰的好处:
setInterval(() => {
common.fetchApi('/api/v1/list', { status: idle.idle ? 'away' : 'online' }).then(/* show a list of elements */)
}, 1000 * 5)
你为什么要一张惰性支票?有时我们使用周期性的XHR(带setInterval),即当用户观看航班、乘车、电影、订单等列表时。对于每个XHR,我们可以添加关于他/她的活动状态(在线/离开)的信息,这样我们就可以了解系统中的活跃用户。
我的课程是基于Equiman和Frank Conijn的回答。
所有这些解决方案的问题,尽管是正确的,但在使用PHP、. net或在应用程序中考虑会话超时值集时,它们是不切实际的。为ColdFusion开发人员提供cfc文件。
上述解决方案设置的时间需要与服务器端会话超时同步。如果两者不同步,您可能会遇到一些问题,这些问题只会让用户感到沮丧和困惑。
例如,服务器端会话超时可能被设置为60分钟,但用户可能认为他/她是安全的,因为JavaScript空闲时间捕获增加了用户在单个页面上花费的总时间。用户可能花了很多时间填写一个很长的表单,然后去提交。会话超时可能在处理表单提交之前开始。
我倾向于只给用户180分钟,然后使用JavaScript自动注销用户。实际上,使用上面的一些代码来创建一个简单的计时器,但是没有捕获鼠标事件部分。
通过这种方式,我的客户端和服务器端时间完全同步。如果您在UI中向用户显示时间,就不会出现混乱。每次在CMS中访问一个新页面时,服务器端会话和JavaScript计时器都会被重置。简单而优雅。如果一个用户在一个页面上停留超过180分钟,首先我认为这个页面有问题。
下面是一个在Angular中完成的AngularJS服务。
/* Tracks now long a user has been idle. secondsIdle can be polled
at any time to know how long user has been idle. */
fuelServices.factory('idleChecker',['$interval', function($interval){
var self = {
secondsIdle: 0,
init: function(){
$(document).mousemove(function (e) {
self.secondsIdle = 0;
});
$(document).keypress(function (e) {
self.secondsIdle = 0;
});
$interval(function(){
self.secondsIdle += 1;
}, 1000)
}
}
return self;
}]);
请记住,这个空闲检查器将为所有路由运行,因此应该在angular应用程序加载时在.run()中初始化它。然后你可以使用idleChecker。在每个路由内的secondside。
myApp.run(['idleChecker',function(idleChecker){
idleChecker.init();
}]);