How to call javascript function only once during window resize event?

On jQuery resize event page it is said that:

"Code in a resize handler should never rely on the number of times the handler is called. Depending on implementation, resize events can be sent continuously as the resizing is in progress (the typical behavior in Internet Explorer and WebKit-based browsers such as Safari and Chrome), or only once at the end of the resize operation (the typical behavior in Firefox)."

Right now I observe increasing memory leak in my app, as I'm continuously resizing browser window, which in it's turn continuously triggers specific code. I thought resize event is called only once in the end of the resize operation, but now after reading this I think my code is simply overkilling itself.

Is there any established practice to trigger a callback cross-browser only once, when resize operation has already ended?

Answers


As you are using jQuery anyway, have a look at Ben Alman's doTimeout plugin. You can use it to debounce your event handler.

There is even an example that matches exactly your case:

$(window).resize(function(){
  $.doTimeout( 'resize', 250, function(){
    // do something computationally expensive
  });
});

The key here is that, the function passed to doTimeout is only executed if the resize handler is not called (i.e. the resize event is not fired) again during the next 250 ms. If so, the timer is aborted and a new one is started.


So this answer I think is best served by doing the following instead of the $.doTimeout method (which seems to not want to run inside of another JQuery statement:

// create a global timer var:
var _timeVar;

// create your jQuery window resize method. The clearTimeout() method prevents the
$(window).resize(function(){
    clearTimeout( _timerVar );
    _timerVar = setTimeout('resizeUI()', 250);
});

// my resize function
function resizeUI() {
    // resize stuff here
}

I think it would help if you showed us your resize event handler.

Without seeing your code all I can suggest is to have some kind of thottle to limit how many times the handler can be triggered per second:

var lastTime = 0;
$(window).resize(function(){
    // This condition will only be met (at most) once every second
    if (lastTime + 1000 < +new Date) {
        // do your stuff...
        lastTime = +new Date;
    }
});

You could use a flag. Set the flag at the start of the function - unset if after the resize in complete. Then do not allow the function to be called again unless the flag has been reset.


Thanks for the tip but I don't think it would work on a browser like IE or Webkit that fire events continuously while resizing. Here is why : Let say that the window has not been resized for several seconds and then you resize it : At the first event fired the lastTime var will be smaller than new Date so the code for resizing will e executed. As the other events are fired at high rate while resizing they will all fall short of one second and will not fire.End result is that the resize will not happen for the final window size which is the one we are trying to capture.

Please let me now if I misunderstood your code, because I am looking for a solution for this and I'd like to avoid having too many timers involved as in other solutions proposed.

Thanks.


I got multiple calls when Firefox is starting (working in XUL Addon). If you want to call your code just ONCE in a time (errors caused when code called over again while your code is already running) you can use just a trigger (flag [boolean value]).

MyClass = {
  is_resizing: false,
  // another variables here...

  resized: function() {
    if (! MyClass.is_resizing) {
      // your code goes here...
    }
  },

  // another methods here...
};

window.addEvenetListener('resize', function(e) { MyClass.resized(); e.stopPropagation(); }, false);

Need Your Help

how does Java url.openStream() work

url-routing

I have used the Java command url.openStream() many times to retrieve data from the web. However, I don't have any idea what it's doing. Does it go through my browser, does it establish a separate ...