降低Javascript事件轮询的频率

时间:2010-12-07 02:04:30

标签: javascript javascript-events event-handling onresize onscroll

如何降低javascript事件轮询的频率?我关注的事件是 onResize onScroll 。当有人调整浏览器大小或向下滚动时,这些事件可能会每秒触发几十次。我希望这些事件每500毫秒才会发生一次,所以我不必花费数小时优化我的事件处理程序并确保它们不会泄漏内存。

6 个答案:

答案 0 :(得分:9)

var resizeTimeout;

window.onresize = function() {
    if (resizeTimeout) {
        clearTimeout(resizeTimeout);
    }
    resizeTimeout = setTimeout(function() {
        // Do it!
    }, 500);

});

这将在人完成大小调整后触发setTimeout()函数~500ms。

onscroll版本非常相似:)

答案 1 :(得分:5)

你不能真正控制事件发生的频率,你可以做一些事情,比如记住第一次事件发射的时间,然后在每个结果事件上你检查它是否超过500毫秒来自第一个 - 如果是,你继续使用事件处理程序,否则只需退出事件hanlder

答案 2 :(得分:1)

在处理程序的开头,检查自上一个处理程序以来是否已经过了500毫秒,如果没有则返回。

答案 3 :(得分:1)

您无法阻止这些事件被触发。他们总是那样做。你想要做的是立即停止听,然后处理事件以避免重复。然后在setTimeout之后再次设置整个处理程序。除非有人调整窗口大小,否则不会再发生递归。我在这里使用5000毫秒,因为它更容易看到它在控制台中工作。即使您像spaz一样调整大小,也不应该每隔5秒在FF控制台中看到多个垃圾邮件。

(function staggerListen(){
  window.onresize = function(){
    window.onresize = false;
    console.log('spam');
    setTimeout(staggerListen,5000);
  };
})()

使用逻辑来决定每次处理程序触发时是否执行任何操作仍然在技术上触发处理程序和if语句+查找。那会很重。

答案 4 :(得分:0)

检查下划线debounce功能

  

创建并返回传递函数的新debounced版本,该函数将推迟执行,直到自上次调用之后经过等待毫秒。用于实现仅在输入停止到达后才会发生的行为。例如:渲染Markdown注释的预览,在窗口停止调整大小后重新计算布局,等等。

示例:

window.onscroll = _.debounce(
  function() {
      // do something
  }, 500, false
);

答案 5 :(得分:0)

我曾经在接受的答案上表达它,但问题是,它只在指定的超时后触发。我想要一个能够立即处理调整大小的解决方案。这就是我最终要做的事情。

var _resize_is_busy = false;
var _resize_scheduled = false;
var _resize_precision = 100;

// This register for window resize events. No need to change anything.
$(window).resize(function () {

    if (!_resize_is_busy) {

        // call the scheduler who will do the work and set a timer to
        // check of other resizes occured within a certain period of time

        _resize_scheduler();
    }
    else {

        // the resizer is busy, i.e. a resize have been handled a little
        // time ago and then the scheduler is waiting some time before 
        // handling any other resize. This flag tells the scheduler that
        // a resize event have been receive while he was sleeping.

        _resize_scheduled = true;
    }
});

// This is the scheduler. No need to change anything.
var _resize_scheduler = function () {

    _resize_is_busy = true;
    _resize_scheduled = false;

    setTimeout(function () {

        _resize_is_busy = false;

        if (_resize_scheduled) 
            _handle_resize();

    }, _resize_precision);

    _handle_resize();
}

var _handle_resize = function () {

    console.log('DOING ACTUAL RESIZE');

    // do the work here
    //...
}

我希望这会有所帮助。