在指定时间内没有来自用户的操作时Javascript超时

时间:2011-08-15 22:18:21

标签: javascript timeout

我想在网页上没有来自用户的活动指定的时间内调用js函数。如果有来自用户的活动,则重置超时。我试图搜索,但没有找到任何特别的东西。我熟悉setTimeout()和clearTimeout()以及它们是如何工作的。我在寻找的是在哪里/如何监控用户活动。有没有可以设置和清除计时器的事件?

谢谢。

编辑#1:

此网页有一个输入文本框&一个按钮。这是一种常规的聊天页面。当我说没有用户活动时,我的意思是用户没有在文本框中输入任何内容,或者没有在指定的时间内按任何按钮。 还有一个针对基于触摸的智能手机设备的目标。

编辑#2:

谢谢大家的建议。我已根据提供的多个答案实施了解决方案。因此,我会放弃对所有有帮助的答案,而不是接受一个答案。

7 个答案:

答案 0 :(得分:26)

// Using jQuery (but could use pure JS with cross-browser event handlers):
var idleSeconds = 30;

$(function(){
  var idleTimer;
  function resetTimer(){
    clearTimeout(idleTimer);
    idleTimer = setTimeout(whenUserIdle,idleSeconds*1000);
  }
  $(document.body).bind('mousemove keydown click',resetTimer); //space separated events list that we want to monitor
  resetTimer(); // Start the timer when the page loads
});

function whenUserIdle(){
  //...
}

编辑:出于什么原因不使用jQuery?这里有一些(未经测试的)代码应该是跨浏览器清理的(例如;在IE5 Mac上不起作用;):

attachEvent(window,'load',function(){
  var idleSeconds = 30;
  var idleTimer;
  function resetTimer(){
    clearTimeout(idleTimer);
    idleTimer = setTimeout(whenUserIdle,idleSeconds*1000);
  }
  attachEvent(document.body,'mousemove',resetTimer);
  attachEvent(document.body,'keydown',resetTimer);
  attachEvent(document.body,'click',resetTimer);

  resetTimer(); // Start the timer when the page loads
});

function whenUserIdle(){
  //...
}

function attachEvent(obj,evt,fnc,useCapture){
  if (obj.addEventListener){
    obj.addEventListener(evt,fnc,!!useCapture);
    return true;
  } else if (obj.attachEvent){
    return obj.attachEvent("on"+evt,fnc);
  }
} 

答案 1 :(得分:9)

这需要辩护人:

function debounce(callback, timeout, _this) {
    var timer;
    return function(e) {
        var _that = this;
        if (timer)
            clearTimeout(timer);
        timer = setTimeout(function() { 
            callback.call(_this || _that, e);
        }, timeout);
    }
}

像这样使用:

// we'll attach the function created by "debounce" to each of the target
// user input events; this function only fires once 2 seconds have passed
// with no additional input; it can be attached to any number of desired
// events
var userAction = debounce(function(e) {
    console.log("silence");
}, 2000);

document.addEventListener("mousemove", userAction, false);
document.addEventListener("click", userAction, false);
document.addEventListener("scroll", userAction, false);

第一个用户操作(mousemove,click或scroll)启动一个函数(附加到计时器),每次发生另一个用户操作时,该函数都会重置。在没有操作的指定时间内,主要回调不会触发。

请注意,无全局标志或超时变量是必需的。全局范围仅接收您的去抖回调。 谨防需要维护全球状态的解决方案;在更大的应用程序中,它们很难被推理出来。

另请注意此解决方案完全是通用的。请注意仅适用于极端狭窄用例的解决方案。

答案 2 :(得分:5)

大多数JavaScript事件bubble,因此您可以执行以下操作:

  • 列出您认为是“来自用户的活动”的所有活动的列表(例如clickmousemovekeydown等。)
  • 将一个函数作为所有这些事件的事件监听器附加到document(或者对于其中一些事件可能document.body;我不记得这是否是一个问题。)
  • 触发侦听器时,请使用clearTimeout / setTimeout重置计时器

所以你最终得到这样的东西:

var events = ['click', 'mousemove', 'keydown'],
    i = events.length,
    timer,
    delay = 10000,
    logout = function () {
        // do whatever it is you want to do
        // after a period of inactivity
    },
    reset = function () {
        clearTimeout(timer);
        timer = setTimeout(logout, 10000);
    };

while (i) {
    i -= 1;
    document.addEventListener(events[i], reset, false);
}
reset();

请注意,使用上述代码时,您需要解决一些问题:

  • 它不是跨浏览器兼容的。它只使用addEventListener,因此在IE6-8中不起作用
  • 它会污染全局命名空间。它会创建许多可能与其他脚本冲突的多余变量。

更多的是让你知道你能做些什么。

现在还有其他四个答案,但我已经输入了所有内容,所以:P

答案 3 :(得分:3)

您希望在文档级别监控mousemovekeypresskeydown和/或click等事件。

修改:这是一款智能手机应用,可以更改您想要收听的内容。根据您的文本框和按钮要求,我会收听oninput,然后将resetTimeout()调用添加到按钮的点击处理程序中。

var inactivityTimeout = 0;
function resetTimeout() {
    clearTimeout(inactivityTimeout);
    inactivityTimeout = setTimeout(inactive, 300000);
}
function inactive() {
   ...
}
document.getElementById("chatInput").oninput = resetTimeout;

答案 4 :(得分:2)

这样的事情:

function onInactive(ms, cb){   

    var wait = setTimeout(cb, ms); 

    // Bind all events you consider as activity
    // Note that binding this way overrides any previous events bound the same wa
    // So if you already have events bound to document, use AddEventListener and AttachEvent instead
    document.onmousemove = document.mousedown = document.mouseup = document.onkeydown = document.onkeyup = document.focus = function(){
        clearTimeout(wait);
        wait = setTimeout(cb, ms);

    };

}

IE:http://jsfiddle.net/acNfy/ 右下方框架中的活动将延迟回调。

答案 5 :(得分:1)

我在this thread

中找到了一个漂亮的小'延迟'方法
var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

使用

delay(function(){ doSomethingWhenNoInputFor400ms(); },400);

答案 6 :(得分:0)

另外,请查看Paul Irish(jQuery idleTimer plugin)的jquery.idle-timer.js。它基于Nicholas C. Zakas的Detecting if the user is idle with JavaScript and YUI 3文章(idle-timer.js)。

它会查看与其他答案类似的事件,再加上其他一些答案。

events  = 'mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove';
// activity is one of these events