是否有可能在JavaScript中检测“空闲”时间?
我的主要用例可能是预取或预加载内容。
我将空闲时间定义为用户不活动或没有任何CPU使用的时间段
是否有可能在JavaScript中检测“空闲”时间?
我的主要用例可能是预取或预加载内容。
我将空闲时间定义为用户不活动或没有任何CPU使用的时间段
当前回答
您可以在文档主体上附加一个单击或鼠标移动事件,以重置计时器。
有一个函数,你在定时间隔调用,检查定时器是否超过指定的时间(如1000毫秒),并开始你的预加载。
其他回答
我写了一个简单的jQuery插件,将做什么你正在寻找。
https://github.com/afklondon/jquery.inactivity
$(document).inactivity( {
interval: 1000, // the timeout until the inactivity event fire [default: 3000]
mouse: true, // listen for mouse inactivity [default: true]
keyboard: false, // listen for keyboard inactivity [default: true]
touch: false, // listen for touch inactivity [default: true]
customEvents: "customEventName", // listen for custom events [default: ""]
triggerAll: true, // if set to false only the first "activity" event will be fired [default: false]
});
脚本将监听鼠标,键盘,触摸和其他自定义事件不活动(空闲),并触发全局“活动”和“不活动”事件。
是否有可能每10秒运行一个函数,并检查一个“计数器”变量?如果可能的话,你可以在页面上进行鼠标悬停,不是吗?
如果是,使用鼠标悬停事件重置“counter”变量。如果函数被调用,并且计数器在您预先确定的范围之上,那么执行您的操作。
下面是一个在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();
}]);
我在这里提出的实现方法与其他答案在以下方面有所不同:
the idle event (by default named 'idleTimeSeconds') is fired every 10 seconds, so you can have multiple subscribers to the same event there is only one timer set per the document instance the timer is fired more often then the idle event (by default every 1 second vs every 10 seconds) - this will make for the default interval precision the timestamp of when the idle time started is recorded and is used to calculate the total idle time; other solutions propose to incrementally add seconds to the idle time counter, which is less prices because the actual delay of a timer may be longer than configured, see "Reasons for delays longer than specified in WindowOrWorkerGlobalScope.setTimeout()" for examples. the timer is never cancelled / reset, as proposed by some other solutions; cancelling and resetting timers is more expensive
文件Idle.js:
import $ from 'jquery';
export const IDLE_EVENT_NAME = 'idleTimeSeconds';
/**
* How often an 'idleTimeSeconds' event is fired on the document instance.
*
* @type {number}
*/
const IDLE_EVENT_RATE_SECONDS = 10;
/**
* How often the idle time is checked against the IDLE_EVENT_RATE_SECONDS.
*
* Should be much smaller than the value of IDLE_EVENT_RATE_SECONDS
* (the smaller the value is, the more precisely the event is fired) -
* because the actual delay may be longer, see "Reasons for delays
* longer than specified in WindowOrWorkerGlobalScope.setTimeout() for examples":
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified
*
* @type {number}
*/
const IDLE_TIMER_RATE_SECONDS = 1;
/**
* Because the actual timer delay may be longer, we track the timestamp
* when the idle time started, instead of incrementally adding to the total idle time.
* Having a starting point, we can always calculate the idle time precisely
* without accumulating delay errors.
*
* @type {number}
*/
let idleStartTimeMilliseconds;
/**
* Holds the interval reference.
*/
let idleInterval;
/**
* Holds the value of the latest idle time value
* for which the event was fired (integer value in seconds).
*
* The value is therefore factor of IDLE_EVENT_RATE_SECONDS.
*
* @type {number}
*/
let lastFiredSeconds;
const $document = $(document);
/**
* Resets the idle timer.
* Called on user interaction events, like keydown or touchstart.
*/
function resetIdleStartTime() {
// Reset the timestamp when the idle time started
idleStartTimeMilliseconds = (new Date).getTime();
// Reset the latest idle time value for which the even was fired
// (integer value in seconds).
lastFiredSeconds = 0;
}
/**
* Ticks every IDLE_TIMER_RATE_SECONDS, which is more often than the expected
* idle event firing rate.
*
* Fires the 'idleTimeSeconds' event on the document instance.
*/
function timerCallback() {
const nowMilliseconds = (new Date).getTime();
const idleTimeSeconds = Math.floor((nowMilliseconds - idleStartTimeMilliseconds) / 1000);
// When do we expect the idle event to be fired again?
// For example, if the event firing rate is 10 seconds,
// and last time it was fired at 40 seconds of idle time,
// the next one will be at 40 + 10 = 50 seconds.
const nextIdleSecondsToFire = lastFiredSeconds + IDLE_EVENT_RATE_SECONDS;
if (idleTimeSeconds >= nextIdleSecondsToFire) {
// Record last fired idle time that is factor of the rate,
// so that we keep firing the event as close to the desired rate as possible
lastFiredSeconds = nextIdleSecondsToFire;
$document.triggerHandler(IDLE_EVENT_NAME, [idleTimeSeconds]);
}
}
// Initialize the idle timer once only per the document instance
$(function() {
// Start the idle timer
idleInterval = setInterval(timerCallback, IDLE_TIMER_RATE_SECONDS * 1000);
// Reset the idle time start timestamp
$document.on('mousemove keydown mousedown touchstart', resetIdleStartTime);
});
示例用法(例如文件index.js):
import {IDLE_EVENT_NAME} from './Idle';
import $ from 'jquery';
$(function() {
$(document).on(IDLE_EVENT_NAME, function(e, idleSeconds) {
console.log('IDLE SECONDS:', idleSeconds);
});
});
示例输出(节选):
IDLE SECONDS: 580
IDLE SECONDS: 590
IDLE SECONDS: 600
IDLE SECONDS: 610
IDLE SECONDS: 620
IDLE SECONDS: 630
IDLE SECONDS: 640
IDLE SECONDS: 650
IDLE SECONDS: 660
IDLE SECONDS: 670
IDLE SECONDS: 680
IDLE SECONDS: 691
IDLE SECONDS: 700
IDLE SECONDS: 710
IDLE SECONDS: 720
IDLE SECONDS: 730
IDLE SECONDS: 740
IDLE SECONDS: 750
IDLE SECONDS: 761
IDLE SECONDS: 770
IDLE SECONDS: 780
IDLE SECONDS: 790
IDLE SECONDS: 800
IDLE SECONDS: 810
IDLE SECONDS: 820
IDLE SECONDS: 830
IDLE SECONDS: 840
IDLE SECONDS: 850
IDLE SECONDS: 860
IDLE SECONDS: 871
IDLE SECONDS: 880
IDLE SECONDS: 890
IDLE SECONDS: 900
IDLE SECONDS: 910
IDLE SECONDS: 921
上面的输出是当我切换到另一个选项卡并在那里做一些活动时产生的。可以看到,计时器有时会延迟(我想是因为在后台选项卡中,计时器以精确的速率被触发不是优先级)。但是空闲计时器仍然以正确的+/- 1秒的间隔触发。在这种情况下,1秒是空闲计时器的精度(通过idle .js中的IDLE_TIMER_RATE_SECONDS常量配置)。
您可能可以通过检测窗体主体上的鼠标移动并使用最后的移动时间更新全局变量来拼凑一些东西。然后,您需要运行一个间隔计时器,定期检查最后一次移动时间,如果距离检测到最后一次鼠标移动已经足够长,则执行一些操作。