-1

Having a massive mind blank, can someone explain why setTimeout is not working inside this while loop:

http://jsbin.com/aHAcIsE/1/edit

var checks = document.querySelectorAll('input[type="checkbox"]'),
    i = checks.length,
    arr = [1, 4, 7];

function check(index){
  checks[index].checked = true;
}

while(i--){
  if(arr.indexOf(i) > -1){
    setTimeout(function(){
      check(i);
    }, 1000);        
  }
}
benhowdle89
  • 36,900
  • 69
  • 202
  • 331
  • Why the heck would you want to set a timeout inside a loop? – subZero Oct 30 '13 at 10:15
  • 4
    typical callback and loop problem - `i` is already zero by the time the timeouts have elapsed. – Alnitak Oct 30 '13 at 10:15
  • Try using an interval here instead. – subZero Oct 30 '13 at 10:15
  • 1
    I think you should use 'setInterval' – Ankit Tyagi Oct 30 '13 at 10:17
  • What is it that you are trying to do? The variable `i` seems to be intended as an index in the array, but then you use `indexOf` to look for the value of `i` in the array, which means that only the first item in the array will be used. – Guffa Oct 30 '13 at 10:20
  • 1
    @Tyagi the OP apparently wants a constrained number of callbacks to be fired - why on earth do you think `setInterval` would help?! – Alnitak Oct 30 '13 at 10:29
  • You know that incorrect answer you gave to this question? Same thing. http://stackoverflow.com/questions/19546726/opening-new-pages-with/19546804 – Joe Oct 30 '13 at 15:59

1 Answers1

2

Your problem is, that when the callback of the setTimeout() is finally executed, all calls of that callback refer to the same variable i, which has the same value for all instances.

Straight forward solution (submit i as a parameter to the callback; then each callback receives its own copy of i). (The additional passing of parameters is not supported by IE<9 according to MDN, so we need a slightly modified version for those browsers.)

// IE9+ version
while(i--){
  if(arr.indexOf(i) > -1){
    setTimeout(function( index ){
      check(index);
    }, 1000, i );        
  }
}

// for IE below version 9
while(i--){
  if(arr.indexOf(i) > -1){
    !function( index ) {
      setTimeout(function(){
        check(index);
      }, 1000 ); 
    }( i );       
  }
}

Restructuring solution (here no callbacks inside a loop are needed and hence the problem does not exist):

setTimeout( function(){   
  while(i--){
    if(arr.indexOf(i) > -1){
      check(index);
    }   
  } 
}, 1000 );
Sirko
  • 72,589
  • 19
  • 149
  • 183