是否有可能在JavaScript中检测“空闲”时间?
我的主要用例可能是预取或预加载内容。
我将空闲时间定义为用户不活动或没有任何CPU使用的时间段
是否有可能在JavaScript中检测“空闲”时间?
我的主要用例可能是预取或预加载内容。
我将空闲时间定义为用户不活动或没有任何CPU使用的时间段
当前回答
(部分灵感来自Equiman回答的良好核心逻辑。)
sessionExpiration.js
sessionExpiration.js是轻量级的,但有效和可定制的。一旦实现,只在一行中使用:
sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
Affects all tabs of the browser, not just one. Written in pure JavaScript, with no dependencies. Fully client side. (If so wanted.) Has warning banner and countdown clock, that is cancelled by user interaction. Simply include the sessionExpiration.js, and call the function, with arguments [1] number of idle minutes (across all tabs) until user is logged out, [2] number of idle minutes until warning and countdown is displayed, and [3] logout url. Put the CSS in your stylesheet. Customize it if you like. (Or skip and delete banner if you don't want it.) If you do want the warning banner however, then you must put an empty div with ID sessExpirDiv on your page (a suggestion is putting it in the footer). Now the user will be logged out automatically if all tabs have been inactive for the given duration. Optional: You may provide a fourth argument (URL serverRefresh) to the function, so that a server side session timer is also refreshed when you interact with the page.
这是一个例子,如果你不改变CSS,它看起来是什么样子的。
其他回答
所有这些解决方案的问题,尽管是正确的,但在使用PHP、. net或在应用程序中考虑会话超时值集时,它们是不切实际的。为ColdFusion开发人员提供cfc文件。
上述解决方案设置的时间需要与服务器端会话超时同步。如果两者不同步,您可能会遇到一些问题,这些问题只会让用户感到沮丧和困惑。
例如,服务器端会话超时可能被设置为60分钟,但用户可能认为他/她是安全的,因为JavaScript空闲时间捕获增加了用户在单个页面上花费的总时间。用户可能花了很多时间填写一个很长的表单,然后去提交。会话超时可能在处理表单提交之前开始。
我倾向于只给用户180分钟,然后使用JavaScript自动注销用户。实际上,使用上面的一些代码来创建一个简单的计时器,但是没有捕获鼠标事件部分。
通过这种方式,我的客户端和服务器端时间完全同步。如果您在UI中向用户显示时间,就不会出现混乱。每次在CMS中访问一个新页面时,服务器端会话和JavaScript计时器都会被重置。简单而优雅。如果一个用户在一个页面上停留超过180分钟,首先我认为这个页面有问题。
你肯定想知道window.requestIdleCallback(),它在浏览器空闲期间对要调用的函数进行排队。
您可以在Quicklink repo中看到这个API的优雅用法。
const requestIdleCallback = window.requestIdleCallback ||
function (cb) {
const start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
},
});
}, 1);
};
上面代码的意思是:如果浏览器支持requestIdleCallback(检查兼容性),就使用它。如果不支持,则使用setTimeout(()=>{}, 1)作为回退,它应该在事件循环结束时将被调用的函数排队。
然后你可以这样使用它:
requestIdleCallback(() => {...}, {
timeout: 2000
});
第二个参数是可选的,如果希望确保函数执行,则可能需要设置一个超时。
试试这段代码。它工作得很完美。
var IDLE_TIMEOUT = 10; //seconds
var _idleSecondsCounter = 0;
document.onclick = function () {
_idleSecondsCounter = 0;
};
document.onmousemove = function () {
_idleSecondsCounter = 0;
};
document.onkeypress = function () {
_idleSecondsCounter = 0;
};
window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
alert("Time expired!");
document.location.href = "SessionExpired.aspx";
}
}
Debounce其实是个好主意!下面是一个用于无jquery项目的版本:
const derivedLogout = createDerivedLogout(30);
derivedLogout(); // It could happen that the user is too idle)
window.addEventListener('click', derivedLogout, false);
window.addEventListener('mousemove', derivedLogout, false);
window.addEventListener('keyup', derivedLogout, false);
function createDerivedLogout (sessionTimeoutInMinutes) {
return _.debounce( () => {
window.location = this.logoutUrl;
}, sessionTimeoutInMinutes * 60 * 1000 )
}
你也许可以使用上面列出的鼠标移动技巧来检测网页上的不活跃状态,但这并不能告诉你用户不在另一个窗口或选项卡的另一个页面上,或者用户在Word、Photoshop或WoW中,只是在这个时候没有在看你的页面。
一般来说,我只会预取,并依赖于客户端的多任务处理。如果你真的需要这个功能,你可以在Windows中使用ActiveX控件做一些事情,但它充其量是丑陋的。