Nagendra Somayaji
Nagendra Somayaji

Reputation: 181

Window.resize() is slowing down as number of resize increases

I am calling some code when my window is completely resized by the help of window.resize() event and with the help of this link. it has worked, but problem is it will become slow as you perform re-size more than 3 times. So as you increase the number of re-size, the page becomes slower and slower.

My code is like below,

 $(window).bind('resize', function(e) {
     window.resizeEvt;
     $(window).resize(function() {
         clearTimeout(window.resizeEvt);
         window.resizeEvt = setTimeout(function() {
             //code to do after window is resized
         }, 250);
     });
 });

Can any one help me to identify why its slowing down?

Upvotes: 0

Views: 1980

Answers (3)

Rycochet
Rycochet

Reputation: 2938

The problem with any timeout based code is that if the user resizes the window slowly then it can fire multiple times for the resize (which includes this code) - if it's just a case of updating the display then my own preference is to use requestAnimationFrame to make sure that it is as clean as possible for this update -

var resizing = false,
    processingResize = false;

function processResize() {
    if (resizing) {
        resizing = false;
        window.requestAnimationFrame(processResize);
    } else {
        processingResize = false;
        // Do stuff here
    }
}

$(window).on("resize", function(event) {
    if (!resizing && event.target === window) {
        resizing = true;
        if (!processingResize ) {
            processingResize = true;
            window.requestAnimationFrame(processResize);
        }
    }
});

Generally I actually have a wrapper for rAF that checks document.hidden and uses a setTimeout when the page isn't visible - but that's not relevant for a simple use as it'll be called once when the page becomes visible again and any resizing can happen then.

If you're trying to detect when a user has completely finished resizing then there's no absolute method, but incorporating mousemove events would catch it more accurately.

Upvotes: 1

Yanick Rochon
Yanick Rochon

Reputation: 53576

The window resize event is fired every time the browser is resized, for every pixels and not only once; the event is not delayed. Futhermore, what you do is to manually execute your resize event... while your are in your resize event. You don't need to call $(window).resize! You only need to bind the event once (and .bind is deprecated, in favour of .on now).

You solution is to throttle what you execute when the browser is being resized. This problem, I have personally solved in a few projects and the code works very well.

/**
  Author: [email protected]
  License: MIT

  Return a copy of the function fn that can be called multiple times.
  The function fn will actually be called if 1) a certain amount of
  time elapsed after the last call, or 2) a certain number of repetitive
  calls have been made.

  The function fn will be invoked with the last arguments sent through
  the returned proxy function.

  Options are :

    - delay {Numeric}   the number of ms before satisfying the first condition
    - stack {Numeric}   the number of repetitive calls before satisfying the second condition

  NOTE : these conditions are ORed, meaning that fn will be invoked if either
         condition 1) or 2) is met.

  @param {Function} fn       the function to proxy
  @param {Object} options    the key-pair of options
  @param {any} ctx           a context to bind fn to when calling
  @return {Function}         a proxy function.
*/
function asyncProxy(fn, options, ctx) {
  var timer = null;
  var counter = 0;
  var _call = function (args) {
    counter = 0;

    fn.apply(ctx, args);
  };

  ctx = ctx || window;
  options = $.extend({
    delay: 0,
    stack: Infinity
  }, options);

  return function () {
    counter++;

    // prevent calling the delayed function multiple times
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    if (counter >= options.stack) {
      _call(arguments);
    } else {
      var args = arguments;

      timer = setTimeout(function () {
        timer = null;
        _call(args);
      }, options.delay);
    }
  };
}

And you use it like this

var processWindowResize = asyncProxy(function (event) {

  // *** Your code goes here ***

}, {
  delay: 250
});

$(window).on('resize', processWindowResize);

Upvotes: 1

Barr J
Barr J

Reputation: 10927

That's because you never end the re sizing, so The event is going on and on, each and every time is heavier then the other, you can even check your response using fiddler for this.

What you need to do is simple, at the end of the end, when window finished re sizing:

    $(window).off("resize", resizeEvt);

this way you clear the event, turning it off every time the event is executed, so it will not slow down your web page.

Upvotes: 0

Related Questions