Ching Ching
Ching Ching

Reputation: 1049

Problematic browser performance when attaching event handler inside loop

I have a problem when creating plugin. The problem came up when setting new value for variable width.

width variable need to calculate again, if user resizes his browser. If i attach resize event inside loop, it will make trouble performance. I came up with the idea to create closure function for wrapping all CODE. So, when the user resize his browser, i call this function again.

JS :

var self         = this,
    onScrollbarY = function() {
        self.each(function() {  // loop it
            var el           = $(this),
                elLog        = el.find(".scrollbarYLog"),
                width        = $(window).innerWidth(),    // this value will change based on users browser width
                onMouseOver  = function() {
                    elLog.html(width);
                };
            elLog.on("mouseover", onMouseOver);
        });
    };
onScrollbarY(); // call it immediatly

$(window).on("resize", onScrollbarY); // if users resize its browser, call it again for getting new browser width

Is this the correct way to accompolished it? or there are other option which more efficient rather than attach all code again?

Upvotes: 0

Views: 71

Answers (1)

Klemen Slavič
Klemen Slavič

Reputation: 19841

The reason why you had a performance problem in the first place is that every time you called .on('resize', ...), you registered a function that runs on that event. So after 5 resize events, you had 5 functions that were called every time, which is what caused the slow-down.

There are two ways to approach this problem:

  1. only attach one handler to that event (what you ended up doing); or
  2. use the .one('resize', ...) event handler to register a function that will only be triggered on the first next resize event.

Use case #1 is what the majority of developers use and recommend. You create a function (like your onScrollbarY) and you register that function using .on() to be called each time the resize event happens from the moment you register it.

The case #2 is very rare and you probably don't want to use .one() unless you only want to handle the first occurence of that event, and none after that. If you wanted to handle more than one, you would have to call .one() again after the event happens to tell it to listen for that event again.

EDIT: You can simplify your code to the following:

var $window  = $(window),
    width    = $window.innerWidth(), // we know the initial width
    $elLog   = $(".scrollbarYLog"),  // we find the scrollbar element
    onResize = function() {
      width = $window.innerWidth();
    },
    onMouseOver = function() {
      $elLog.html(width);
    };

// register the resize function with the "resize" event
$window.on("resize", onResize);
// register the mouseover function with the "mouseover" event on the scrollbar
$elLog.on("mouseover", onMouseOver);

// there is no need to call onResize(), as we've already set the width variable

Upvotes: 1

Related Questions