如何优雅地检测JavaScript中的空闲时间?

JavaScript

逆天AGreen

2020-03-13

是否可以在JavaScript中检测“ 空闲 ”时间?
我的主要用例可能是预取或预加载内容。

空闲时间:用户不活动或没有使用CPU的时间

第1372篇《如何优雅地检测JavaScript中的空闲时间?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

15个回答
成天 2020.03.13

好吧,您可以将click或mousemove事件附加到文档主体,以重置计时器。有一个您可以按时间间隔调用的函数,该函数可以检查计时器是否超过指定的时间(例如1000毫秒),然后开始预加载。

GONear 2020.03.13

我使用这种方法,因为您不需要在事件触发时不断重置时间,而是只记录时间,这会生成空闲开始点。

           function idle(WAIT_FOR_MINS, cb_isIdle) {
            var self = this, 
                idle,
                ms = (WAIT_FOR_MINS || 1) * 60000,
                lastDigest = new Date(),
                watch;
            //document.onmousemove = digest;
            document.onkeypress = digest;
            document.onclick = digest;

            function digest() {
               lastDigest = new Date(); 
            }
            // 1000 milisec = 1 sec
            watch = setInterval(function(){
                if (new Date() - lastDigest > ms && cb_isIdel) {
                    clearInterval(watch);
                    cb_isIdle();
                }

            }, 1000*60);    
        },
Itachi 2020.03.13

您可能会使用列出的mousemove技巧检测到网页上的不活动状态,但这并不能告诉您该用户不在另一个窗口或选项卡的另一个页面上,或者该用户不在Word或Photoshop中,或者在WOW和只是目前不在看您的页面。通常,我只是做预取并依靠客户端的多任务处理。如果您确实需要此功能,则可以在Windows中使用Activex控件来做一些事情,但这充其量是丑陋的。

西里泡芙 2020.03.13

我写了一个简单的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]
});

该脚本将侦听鼠标,键盘,触摸和其他自定义事件的不活动(空闲),并触发全局“活动”和“不活动”事件。

希望这可以帮助 :)

Jnck 2020.03.13

只是一些想法,一两个探索的途径。

是否可以使函数每10秒运行一次,并检查“计数器”变量?如果可以的话,您可以将鼠标悬停在页面上,可以吗?如果是这样,请使用mouseover事件重置“计数器”变量。如果调用了函数,并且计数器在您预定的范围之上,请执行操作。

再说一遍,只是一些想法...希望能有所帮助。

逆天卡卡西 2020.03.13

所有这些解决方案的问题,尽管是正确的,但考虑到会话超时有价值的设置(使用PHP,.NET或Coldfusion开发人员的Application.cfc文件)时,都是不切实际的。上述解决方案设置的时间需要与服务器端会话超时同步。如果两者不同步,您可能会遇到问题,这些问题只会使您的用户感到沮丧和困惑。例如,服务器端会话超时可能设置为60分钟,但用户可能认为他/她是安全的,因为JavaScript空闲时间捕获增加了用户可以花在单个页面上的总时间。用户可能已经花了很长时间填写较长的表格,然后去提交。会话超时可能在处理表单提交之前开始。我倾向于给用户180分钟,然后使用JavaScript自动将用户注销。本质上,使用上面的一些代码来创建一个简单的计时器,但是没有捕获鼠标事件部分。这样,我的客户端和服务器端时间可以完美同步。如果您在用户界面中向用户显示时间,则不会造成混乱,因为这会减少时间。每次在CMS中访问新页面时,服务器端会话和JavaScript计时器都会重置。简单而优雅。如果用户在一个页面上停留了180分钟以上,那么我认为该页面首先存在问题。随着它减少。每次在CMS中访问新页面时,服务器端会话和JavaScript计时器都会重置。简单而优雅。如果用户在一个页面上停留了180分钟以上,那么我认为该页面首先存在问题。随着它减少。每次在CMS中访问新页面时,服务器端会话和JavaScript计时器都会重置。简单而优雅。如果用户在一个页面上停留了180分钟以上,那么我认为该页面首先存在问题。

宝儿神无 2020.03.13

具有正确设置的重置时间和绑定的纯JavaScript addEventListener

(function() {

  var t,
    timeout = 5000;

  function resetTimer() {
    console.log("reset: " + new Date().toLocaleString());
    if (t) { 
      window.clearTimeout(t); 
    }
    t = window.setTimeout(logout, timeout);
  }

  function logout() {
    console.log("done: " + new Date().toLocaleString());
  }
  resetTimer();

  //And bind the events to call `resetTimer()`
  ["click", "mousemove", "keypress"].forEach(function(name) {
    console.log(name);
    document.addEventListener(name, resetTimer);
  });

}());
小小神奇 2020.03.13

(部分受此线程前面的Equiman良好的核心逻辑的启发。)

sessionExpiration.js


sessionExpiration.js轻巧但有效且可自定义。实施后,只需一行即可使用:

sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
  • 影响浏览器的所有标签,而不仅仅是一个。
  • 纯JavaScript编写,没有依赖关系。完全是客户端。
  • (如果需要的话。)具有警告标语倒计时时钟,可通过用户交互来取消。
  • 只需包含sessionExpiration.js,并使用以下参数调用函数:[1]空闲分钟数(在所有选项卡上),直到用户注销为止;[2]空闲分钟数,直到显示警告和倒数,以及[3]注销网址。
  • 将CSS放入样式表中。如果愿意,可以自定义它。(或者,如果不需要,请跳过并删除横幅。)
  • 但是,如果您确实想要警告横幅,则必须在页面上放置一个ID为sessExpirDiv的空div (建议将其放在页脚中)
  • 现在,如果在给定的时间内所有选项卡都处于非活动状态,则用户将自动注销。
  • 可选:您可以向函数提供第四个参数(URL serverRefresh),以便在与页面交互时也刷新服务器端会话计时器。

如果您不更改CSS,这就是实际操作的示例。

demo_image

飞云前端西门 2020.03.13

试试此代码,它可以完美地工作。

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";
    }
}
null 2020.03.13

如果您要定位受支持的浏览器(截至2018年12月为Chrome或Firefox),则可以尝试使用requestIdleCallback,为不受支持的浏览器添加requestIdleCallback填充程序。

Stafan西门 2020.03.13

通过检测鼠标在表单主体上的移动并在最后一次移动时间更新全局变量,您可能会一起破解某些东西。然后,您需要运行一个间隔计时器,该计时器会定期检查上一次移动时间,并且如果自检测到上一次鼠标移动以来时间足够长,则应执行一些操作。

理查德凯 2020.03.13

先前的所有答案都有一个始终处于活动状态的mousemove处理程序。如果处理程序是jQuery,则jQuery所执行的其他处理可以累加起来。特别是如果用户使用游戏鼠标,则每秒最多可能发生500个事件。

This solution avoids handling every mousemove event. This result in a small timing error, but which you can adjust to your need.

function setIdleTimeout(millis, onIdle, onUnidle) {
    var timeout = 0;
    startTimer();

    function startTimer() {
        timeout = setTimeout(onExpires, millis);
        document.addEventListener("mousemove", onActivity);
        document.addEventListener("keydown", onActivity);
    }

    function onExpires() {
        timeout = 0;
        onIdle();
    }

    function onActivity() {
        if (timeout) clearTimeout(timeout);
        else onUnidle();
        //since the mouse is moving, we turn off our event hooks for 1 second
        document.removeEventListener("mousemove", onActivity);
        document.removeEventListener("keydown", onActivity);
        setTimeout(startTimer, 1000);
    }
}

http://jsfiddle.net/jndxq51o/

猪猪十三 2020.03.13

这是tvanfosson想法的jQuery粗略实现:

$(document).ready(function(){

   idleTime = 0;

   //Increment the idle time counter every second.
   var idleInterval = setInterval(timerIncrement, 1000);

   function timerIncrement()
   {
     idleTime++;
     if (idleTime > 2)
     {
       doPreload();
     }
   }

   //Zero the idle timer on mouse movement.
   $(this).mousemove(function(e){
      idleTime = 0;
   });

   function doPreload()
   {
     //Preload images, etc.
   }

})
米亚小小神乐 2020.03.13

我一年前创建了一个小库:

https://github.com/shawnmclean/Idle.js

描述:

小型的javascript库,用于报告用户在浏览器中的活动(离开,空闲,不查看网页,在其他标签中等)。与其他任何JavaScript库(例如jquery)无关。

Visual Studio用户可以通过以下方式从NuGet中获取它: PM> Install-Package Idle.js

GIZO-俊宏 2020.03.13

这是一个使用JQuery的简单脚本,用于处理mousemove和keypress事件。如果时间到了,页面将重新加载。

<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
    //Increment the idle time counter every minute.
    var idleInterval = setInterval(timerIncrement, 60000); // 1 minute

    //Zero the idle timer on mouse movement.
    $(this).mousemove(function (e) {
        idleTime = 0;
    });
    $(this).keypress(function (e) {
        idleTime = 0;
    });
});

function timerIncrement() {
    idleTime = idleTime + 1;
    if (idleTime > 19) { // 20 minutes
        window.location.reload();
    }
}
</script>   

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android