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

发布于 2024-11-29 21:00:28 字数 389 浏览 0 评论 0 原文

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

谢谢。

编辑#1:

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

编辑 #2:

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

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?

Thank you.

Edit #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:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

甜中书 2024-12-06 21:00:28
// 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);
  }
} 
// 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 ;):

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);
  }
} 
长亭外,古道边 2024-12-06 21:00:28

这需要一个反跳器:

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

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

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

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

This calls for a 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 flags or 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.

山田美奈子 2024-12-06 21:00:28

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

  • 列出一个列表您认为是“用户活动”的所有事件(例如,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

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

  • 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.body for 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

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.

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

当爱已成负担 2024-12-06 21:00:28

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

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

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

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

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

var inactivityTimeout = 0;
function resetTimeout() {
    clearTimeout(inactivityTimeout);
    inactivityTimeout = setTimeout(inactive, 300000);
}
function inactive() {
   ...
}
document.getElementById("chatInput").oninput = resetTimeout;
同尘 2024-12-06 21:00:28

像这样的东西:

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/
右下框架中的活动将延迟回调。

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.

黑色毁心梦 2024-12-06 21:00:28

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

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

类似的用法

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

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);
来世叙缘 2024-12-06 21:00:28

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

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

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

Also, take a look at jQuery idleTimer plugin from Paul Irish (jquery.idle-timer.js). It was based on Nicholas C. Zakas' Detecting if the user is idle with JavaScript and YUI 3 article (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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文