0

I would like to name many setTimeouts differently, so that I can clear each one individually. I tried the following approach:

for(i=0; i<5; i++){

    var wordTimeout = i + "_T_i_m_e_o_u_t";     
    clearTimeout( wordTimeout ); 

    var wordTimeout = setTimeout( function() { console.log( i + ' timeout called' );}, 2000); 
    console.log(i);
}

http://jsfiddle.net/NU4E8/2/

But it looks like I renamed wordTimeout, and then the variable didn't matter. Ideally, in this example all of the setTimeouts would have been individually cleared after being called. So no timeouts would show up in the log. Thanks.

display-name-is-missing
  • 4,424
  • 5
  • 28
  • 41
Squirrl
  • 4,909
  • 9
  • 47
  • 85

3 Answers3

4

You can't name your own timeouts. setTimeout and setInterval return a numeric ID, which is what must be passed into clearTimetout. You can, however, use an array or an object to store your timeouts:

var timeoutIds = [];
for(var i=0; i<5; i++){
    timeoutIds.push(setTimeout(function(){ /* ... */ }));
}

Or, if you need to name them, you can do it like this:

var timeoutIds = {};
for(var i=0; i<5; i++){
    timeoutIds['timeout_' + i] = setTimeout(function(){ /* ... */ });
}

You should also be aware that in your loop, as you've written it, all the timeouts will print '4 timeout called'; that's because the functions are declared in a closure that contains i, and by the time they get around to executing, the loop will have finished, and have the final value 4 (unless it's re-used by other code in the same scope, of course). What you probably want to do is this:

var timeoutIds = [];
for(var i=0; i<5; i++){
    timeoutIds.push(
        (function(i){
            // i now captured as a function-scope variable
            return setTimeout(function(){ console.log(i + ' timeout called'); });
        })(i)
    );
}

This creates an immediately-invoked function expression (IIFE), which "captures" the value of i as a function-scope variable.

Ethan Brown
  • 26,892
  • 4
  • 80
  • 92
3

You can create an array and store the timer references there using the index as the key like

var timers = [];
for (i = 0; i < 5; i++) {
    timers.push(setTimeout(function () {
        console.log(i + ' timeout called');
    }, 2000));
    console.log(i);
}

then access the timer reference for i=0 using timers[0]


You have another common problem known as usage of a closure variable in a loop

Community
  • 1
  • 1
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
0

Create an array where you will store the numbers returned by each of the setTimeout calls.

var timeouts=[];
for(i=0; i<5; i++){    
    clearTimeout(timeouts[i]);
    timeouts[i]=setTimeout((function(){
        console.log(this.i+' timeout called');
    }).bind({i:i}),2000); 
    console.log(i);
}

Then, when you need to do the clearing, you will have the timeout numbers stored by i.

The .bind trick is because of i's scope.

Robbie Wxyz
  • 7,671
  • 2
  • 32
  • 47