Question

How do you lower the frequency of javascript event polling? The events I'm concerned about are onResize and onScroll. These events may be triggered dozens of times per second when someone resizes their browser or scrolls down, respectively. I'd like these events to happen only once every 500 ms so I don't have to spend hours optimizing my event handlers and making sure they don't leak memory.

Was it helpful?

Solution

var resizeTimeout;

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

});

This will trigger the setTimeout() function ~500ms after the person has finished resizing.

The onscroll version is very similar :)

OTHER TIPS

You can't really control how frequently the event fires, you can do something like remember the time of first event firing, then on each consequent one you check if it's more than 500 ms from first one - if yes, you proceed with the event handler, otherwise you just exit the event hanlder

At the beginning of your handler, check to see if 500ms have passed since the last one, and just return if not.

You can't prevent these events from firing. They always do. What you want to do is stop listening immediately, then handle the event to avoid repetition. Then the entire handler is set up again after setTimeout. No more recursion happens unless somebody resizes the window. I use 5000ms here as it's easier to see it working in the console. You shouldn't see more than one spam in the FF console every 5 seconds even if you resize like a spaz.

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

Using logic to decide whether to do anything every time the handler fires is still technically firing a handler and an if statement + lookup. That can get heavy.

check the underscore debounce function

Creates and returns a new debounced version of the passed function that will postpone its execution until after wait milliseconds have elapsed since the last time it was invoked. Useful for implementing behavior that should only happen after the input has stopped arriving. For example: rendering a preview of a Markdown comment, recalculating a layout after the window has stopped being resized, and so on.

Example:

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

I used to make it like on the accepted answer but the problem is, it only triggers after the timeout specified. I wanted a solution that handles the resize right away, the first time. Here is what I ended up doing.

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
    //...
}

I hope this will help.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top