过早执行setTimeout

Premature setTimeout execution

本文关键字:setTimeout 执行      更新时间:2023-09-26

我有一个脚本,应该检查浏览器窗口(鼠标和键盘)上的用户活动,如果5分钟后没有活动,执行注销功能。

简单功能代码如下:

var tempLOT = 300000;
console.log('Auto Logout: ' + tempLOT + ' ms');
var st = new Date().toLocaleTimeString();
console.log('Auto Refresh started: ' + st);
document.onload = function() {
    inactivityTime();
};
document.onmousedown = function() {
    inactivityTime();
};
document.onkeypress = function() {
    inactivityTime();
};
document.ontouchstart = function() {
    inactivityTime();
};
var inactivityTime = function () {
    var t;
    window.onload = resetTimer;
    document.onmousemove = resetTimer;
    document.onkeypress = resetTimer;

    function LOT() {
        console.log("Time to log out");
    }
    function resetTimer() { 
        clearTimeout(t);
        t = setTimeout(LOT, tempLOT);
        var dateObj = Date.now();
        dateObj = dateObj + tempLOT;
        estLOT = new Date(dateObj);
        var ot = new Date().toLocaleTimeString();   
        console.log("Ongoing User Activity: " + ot);
        console.log("Activity Counter: " + t);
        console.log("Estimated LOT: " + estLOT);
    }
};

代码工作正常,当我有tempLOT低于5分钟。其他的都被提前执行了。控制台的输出如下:

Auto Logout: 300000 ms
(index):1 Auto Refresh started: 10:58:08 AM
(index):1 Ongoing User Activity: 10:58:21 AM
(index):1 Activity Counter: 223
(index):1 Estimated LOT: Fri Sep 30 2016 11:03:21 GMT-0400 (Eastern Daylight Time)
(index):1 Ongoing User Activity: 10:58:22 AM
(index):1 Activity Counter: 226
(index):1 Estimated LOT: Fri Sep 30 2016 11:06:57 GMT-0400 (Eastern Daylight Time)
[...] ----------- more user activity here ------
---------------- User left browser window ------------------------
---------- Then user come back to a browser window ---------------
(index):1 Ongoing User Activity: 11:04:01 AM
(index):1 Activity Counter: 8054
(index):1 Estimated LOT: Fri Sep 30 2016 11:09:01 GMT-0400 (Eastern Daylight Time)
(index):1 Ongoing User Activity: 11:04:01 AM
(index):1 Activity Counter: 8056
[...] ------- more user activity here ------
(index):1 Ongoing User Activity: 11:04:07 AM
(index):1 Activity Counter: 8703
(index):1 Estimated LOT: Fri Sep 30 2016 11:09:07 GMT-0400 (Eastern Daylight Time)
(index):1 Ongoing User Activity: 11:04:07 AM
(index):1 Activity Counter: 8705
(index):1 Estimated LOT: Fri Sep 30 2016 11:09:07 GMT-0400 (Eastern Daylight Time)
(index):1 Ongoing User Activity: 11:04:07 AM
(index):1 Activity Counter: 8707
(index):1 Estimated LOT: Fri Sep 30 2016 11:09:07 GMT-0400 (Eastern Daylight Time)
(index):1 Auto Refresh stopped: 11:04:21 AM
(index):1 Time to log out

基于用户活动的注销应该发生在格林尼治时间11:09:07,但在11:04:21执行。

知道发生了什么事吗?

您在inactivityTime中定义t,因此每次调用它时都声明一个新的t,因此其他计时器仍然存在。还有,为什么要重新绑定里面的所有事件?

你的代码应该是

(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);
  });
}());
<p>TEST</p>