是否有可能在JavaScript中检测“空闲”时间?

我的主要用例可能是预取或预加载内容。

我将空闲时间定义为用户不活动或没有任何CPU使用的时间段


当前回答

尝试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();
    });

});

其他回答

JavaScript没有办法告诉CPU的使用情况。这将打破运行在沙盒中的JavaScript。

除此之外,连接页面的onmouseover和onkeydown事件可能会工作。

你也可以在onload事件中使用setTimeout来调度延迟后调用的函数。

// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);

你可以用Underscore.js和jQuery更优雅地做到这一点:

$('body').on("click mousemove keyup", _.debounce(function(){
    // do preload here
}, 1200000)) // 20 minutes debounce
<script type="text/javascript">
    var idleTime = 0;
    $(document).ready(function () {
        //Increment the idle time counter every minute.
        idleInterval = setInterval(timerIncrement, 60000); // 1 minute

        //Zero the idle timer on mouse movement.
        $('body').mousemove(function (e) {
            //alert("mouse moved" + idleTime);
            idleTime = 0;
        });

        $('body').keypress(function (e) {
            //alert("keypressed"  + idleTime);
            idleTime = 0;
        });

        $('body').click(function() {
            //alert("mouse moved" + idleTime);
            idleTime = 0;
        });
    });

    function timerIncrement() {
        idleTime = idleTime + 1;
        if (idleTime > 10) { // 10 minutes

            window.location.assign("http://www.google.com");
        }
    }
</script>

我认为这个jQuery代码是一个完美的,虽然复制和修改从上面的答案!!

不要忘记在你的文件中包含jQuery库!

您可能可以通过检测窗体主体上的鼠标移动并使用最后的移动时间更新全局变量来拼凑一些东西。然后,您需要运行一个间隔计时器,定期检查最后一次移动时间,如果距离检测到最后一次鼠标移动已经足够长,则执行一些操作。

根据equiman提供的输入:

class _Scheduler {
    timeoutIDs;

    constructor() {
        this.timeoutIDs = new Map();
    }

    addCallback = (callback, timeLapseMS, autoRemove) => {
        if (!this.timeoutIDs.has(timeLapseMS + callback)) {
            let timeoutID = setTimeout(callback, timeLapseMS);
            this.timeoutIDs.set(timeLapseMS + callback, timeoutID);
        }

        if (autoRemove !== false) {
            setTimeout(
                this.removeIdleTimeCallback, // Remove
                10000 + timeLapseMS, // 10 secs after
                callback, // the callback
                timeLapseMS, // is invoked.
            );
        }
    };

    removeCallback = (callback, timeLapseMS) => {
        let timeoutID = this.timeoutIDs.get(timeLapseMS + callback);
        if (timeoutID) {
            clearTimeout(timeoutID);
            this.timeoutIDs.delete(timeLapseMS + callback);
        }
    };
}

class _IdleTimeScheduler extends _Scheduler {
    events = [
        'load',
        'mousedown',
        'mousemove',
        'keydown',
        'keyup',
        'input',
        'scroll',
        'touchstart',
        'touchend',
        'touchcancel',
        'touchmove',
    ];
    callbacks;

    constructor() {
        super();
        this.events.forEach(name => {
            document.addEventListener(name, this.resetTimer, true);
        });

        this.callbacks = new Map();
    }

    addIdleTimeCallback = (callback, timeLapseMS) => {
        this.addCallback(callback, timeLapseMS, false);

        let callbacksArr = this.callbacks.get(timeLapseMS);
        if (!callbacksArr) {
            this.callbacks.set(timeLapseMS, [callback]);
        } else {
            if (!callbacksArr.includes(callback)) {
                callbacksArr.push(callback);
            }
        }
    };

    removeIdleTimeCallback = (callback, timeLapseMS) => {
        this.removeCallback(callback, timeLapseMS);

        let callbacksArr = this.callbacks.get(timeLapseMS);
        if (callbacksArr) {
            let index = callbacksArr.indexOf(callback);
            if (index !== -1) {
                callbacksArr.splice(index, 1);
            }
        }
    };

    resetTimer = () => {
        for (let [timeLapseMS, callbacksArr] of this.callbacks) {
            callbacksArr.forEach(callback => {
                // Clear the previous IDs
                let timeoutID = this.timeoutIDs.get(timeLapseMS + callback);
                clearTimeout(timeoutID);

                // Create new timeout IDs.
                timeoutID = setTimeout(callback, timeLapseMS);
                this.timeoutIDs.set(timeLapseMS + callback, timeoutID);
            });
        }
    };
}
export const Scheduler = new _Scheduler();
export const IdleTimeScheduler = new _IdleTimeScheduler();