0

I'm creating a long list of select items and wanted to create a closure call to add each option, then queue the call (via a setTimer) so the browser would not hang.

My implementation works great, but here is what has me puzzled, the following code:

var mainList = $('#mainList');
for (var i=0;i < 100000; i++) {
  var self = mainList, addOption = function() {
    $(self).append('<option value=' + i + '>' + i + '</option>');
   };

  $.queue.add(addOption, this);
}

generates:

<option value='100000'>100000</option>
<option value='100000'>100000</option>
<option value='100000'>100000</option>  etc...

Where I would like to have it generate the options:

<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>  etc...

I'm struggling with how the closure is executed, it makes sense that the addOption() method is called when i == 100000, but I would like the call to reflect the value of i at the time it is queued up.

Is there an easy trick I am missing here?

Mark Kadlec
  • 7,478
  • 15
  • 59
  • 94

2 Answers2

2

Set addOption by IIFE which returns a function

var mainList = $('#mainList');
for (var i = 0; i < 100000; i++) {
    var self = mainList,
        addOption = (function(i) {
            return function() {
                $(self).append('<option value=' + i + '>' + i + '</option>');
            }
        })(i);
    $.queue.add(addOption, this);
}
Community
  • 1
  • 1
AmmarCSE
  • 29,061
  • 5
  • 39
  • 52
2

Prior to the introduction of Function.prototype.bind, it was certainly necessary to employ a closure specifically to trap one or more vars in situations like this.

Now, that approach is considered to be a bit clumsy.

You can define a basic addOption function, then spawn versions of it in the loop, using addOption.bind() to bind in both mainList as "thisArg", and i as the first formal variable :

var mainList = $('#mainList');
var addOption = function(i) {
    this.append('<option value=' + i + '>' + i + '</option>');
};
for (var i=0; i<100000; i++) {
    $.queue.add(addOption.bind(mainList, i), this);
}
Roamer-1888
  • 18,902
  • 5
  • 31
  • 44