当用户在指定时间内没有任何操作时,Javascript 超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7071472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:43:26  来源:igfitidea点击:

Javascript timeout when no actions from user for specified time

javascripttimeout

提问by indusBull

I want to call a js function when there is no activity from user on the web page for specified amount of time. If there is activity from user then reset timeout. I tried to search but couldn't find anything in particular. I am familiar with setTimeout() and clearTimeout() and how they work. What I am looking for is where/how to monitor for user activity. Is there any event in which I can set and clear timer?

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

Thank you.

谢谢你。

Edit #1:

编辑#1:

This webpage has one input text box & one button. It's kind of regular chat page. When I say no user activity, I mean that the user has not typed anything in text box or has not pressed any button for specified amount of time. And one more thing that it is targeted for touch based smartphone devices.

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

Edit #2:

编辑#2:

Thank you everyone for suggestions. I've implemented solution based on more than one answers provided. So I will give upvote to all answers that I've found helpful instead of accepting one as answer.

谢谢大家的建议。我已经根据提供的多个答案实施了解决方案。因此,我将对所有我认为有帮助的答案投赞成票,而不是接受一个作为答案。

回答by Phrogz

// 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(){
  //...
}

Edit: Not using jQuery for whatever reason? Here's some (untested) code that should be cross-browser clean (to a point; doesn't work on IE5 Mac, for example ;):

编辑:无论出于何种原因不使用 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);
  }
} 

回答by Wayne

This calls for a debouncer:

这需要一个 debouncer:

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);
    }
}

Used like this:

像这样使用:

// 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);

The first user action (mousemove, click, or scroll) kicks off a function (attached to a timer) that resets each time another user action occurs. The primary callback does not fire until the specified amount of time has passed with no actions.

第一个用户操作(鼠标移动、单击或滚动)启动一个功能(附加到计时器),每次发生另一个用户操作时都会重置该功能。直到指定的时间量过后没有任何操作,主回调才会触发。

Note that no global flagsor timeout variables are needed. The global scope receives only your debounced callback. Beware of solutions that require maintenance of global state; they're going to be difficult to reason about in the context of a larger application.

请注意,不需要全局标志或超时变量。全局范围仅接收您的去抖动回调。注意需要维护全局状态的解决方案;在更大的应用程序的上下文中,它们将很难推理。

Note also that this solution is entirely general. Beware of solutions that apply only to your extremely narrow use case.

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

回答by sdleihssirhc

Most JavaScript events bubble, so you could do something like the following:

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

  • Come up with a list of all the events you'd consider to be "activity from the user" (e.g., click, mousemove, keydown, etc.)
  • Attach one function as an event listener for all of those events to document(or maybe document.bodyfor some of them; I can't remember if that's an issue or not).
  • When the listener is triggered, have it reset the timer with clearTimeout/setTimeout
  • 列出您认为是“来自用户的活动”的所有事件(例如clickmousemovekeydown、 等)
  • 将一个函数作为所有这些事件的事件侦听器附加到document(或者可能document.body是其中一些事件;我不记得这是否是一个问题)。
  • 当监听器被触发时,让它用clearTimeout/重置计时器setTimeout

So you'd end up with something like this:

所以你最终会得到这样的结果:

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();

Note that there are some issues you'd have to work out with the above code:

请注意,您必须使用上述代码解决一些问题:

  • It's not cross-browser compatible.It only uses addEventListener, so it won't work in IE6-8
  • It pollutes the global namespace.It creates a lot of excess variables that might conflict with other scripts.
  • 它不跨浏览器兼容。它只使用addEventListener,所以它不会在 IE6-8 中工作
  • 它污染了全局命名空间。它创建了许多可能与其他脚本冲突的多余变量。

It's more to give you an idea of what you could do.

更重要的是让您了解您可以做什么。

And now there are four other answers, but I've already typed it all up, so there :P

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

回答by gilly3

You want to monitor events like mousemove, keypress, keydown, and/or clickat the document level.

要监视样事件mousemovekeypresskeydown,和/或click在文档级别。

Edit:This being a smartphone app changes what events you want to listen for. Given your textbox and button requirements, I'd listen to oninputand then add the resetTimeout()call to the click handler for your button.

编辑:这是一款智能手机应用程序,可以更改您想要收听的事件。考虑到您的文本框和按钮要求,我会听取oninput然后将resetTimeout()调用添加到您的按钮的点击处理程序。

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

回答by Paul

Something like this:

像这样的东西:

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/Activity in the bottom right frame will delay the callback.

IE: http://jsfiddle.net/acNfy/右下框的Activity会延迟回调。

回答by Flion

I'm using a nifty little 'delay' method for this that I found in this thread

我在这个线程中找到了一个漂亮的小“延迟”方法

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

use like

使用喜欢

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

回答by Kevin Hakanson

Also, take a look at jQuery idleTimer pluginfrom Paul Irish (jquery.idle-timer.js). It was based on Nicholas C. Zakas' Detecting if the user is idle with JavaScript and YUI 3article (idle-timer.js).

另外,看看Paul Irish ( jquery.idle-timer.js) 的jQuery idleTimer 插件。它基于 Nicholas C. Zakas使用 JavaScript 和 YUI 3文章 ( idle-timer.js)检测用户是否空闲

It looks at similar events to the other answers, plus a few more.

它着眼于与其他答案类似的事件,以及更多。

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