6

Как снизить частоту опроса событий javascript? События, которые меня волнуют, - onResize и onScroll. Эти события могут срабатывать десятки раз в секунду, когда кто-то изменяет размер своего браузера или прокручивает вниз соответственно. Я бы хотел, чтобы эти события происходили только один раз каждые 500 мс, поэтому мне не нужно тратить часы на оптимизацию обработчиков событий и убедиться, что они не утечки памяти.Уменьшить частоту опроса Javascript

ответ

9
var resizeTimeout; 

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

}); 

Это вызовет к setTimeout() функции ~ 500мс после того, как человек закончил изменение размера.

версия onscroll очень похожа :)

+3

этот не будет срабатывать каждые 500 мс, он срабатывает только 500 мс после остановки/паузы изменения размера – Andrey 2010-12-07 02:09:42

+0

+1 избили меня. Не забудьте включить проверку для `resizeTimeout`, так как это будет` undefined` в первый раз. – casablanca 2010-12-07 02:10:23

+0

@ Andrey: Хорошая точка - я не обратил внимания на это. – casablanca 2010-12-07 02:11:59

5

Вы не можете контролировать то, как часто срабатывает событие, вы можете сделать что-то вроде помню время первого обжига событий, а затем на каждом последующим один проверить, если это более 500 мс от первого - если да, вы переходите к обработчику событий, иначе вы просто выходите из события hanlder

1

В начале вашего обработчика проверьте, прошло ли 500 м с момента последнего, и просто если нет.

1

Вы не можете предотвратить эти события от стрельбы. Они всегда это делают. То, что вы хотите сделать, это немедленно прекратить прослушивание, а затем обработать событие, чтобы избежать повторения. Затем весь обработчик настроен снова после setTimeout. Больше нет рекурсии, если кто-то не изменяет размер окна. Я использую 5000ms здесь, так как легче видеть, как он работает в консоли. Вы не должны видеть больше одного спама в консоли FF каждые 5 секунд, даже если вы изменяете размер как спаз.

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

Используя логику, чтобы решить, следует ли сделать что-нибудь каждый раз, когда обработчик срабатывает еще технически обжиг обработчика и если заявление + поиск. Это может стать тяжелым.

0

проверка подчеркивание debounce функция

Создает и возвращает новую версию противодребезговую защиту переданной функции, которая будет отложить его выполнение, пока не ждать миллисекунд, прошедших с момента последнего времени он был вызван. Полезно для реализации поведения, которое должно произойти только после того, как вход остановился. Например: рендеринг предварительного комментария Markdown, пересчет макета после того, как окно перестало изменяться, и так далее.

Пример:

window.onscroll = _.debounce(
    function() { 
     // do something 
    }, 500, false 
); 
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 
    //... 
} 

Надеюсь, это поможет.