Houshalter
Houshalter

Reputation: 2788

Stopping Nested Timeouts in Javascript

I want to execute a piece of arbitrary code and be able to stop it whenever I want. I figured I could do this with setTimeout and then use clearTimeout to stop it. However if the code in the timeout creates it's own timeouts, then those keep executing even after I clear the original.

Example:

var timeoutID = setTimeout(
    function(){
        console.log("first event can be stopped with clearTimout(timeoutID)");
        setTimeout(function(){console.log("but not this one")}, 5000)
    }, 5000)

Now one way would be to control the code being executed and make it store the value of any additional timeouts into a global variable and clear them all at once. But is there a better way to do this? And is there a way to do this on arbitrary code?

To clarify, I'm trying to be able to execute any function I want, then stop it whenever I want, even if the function contains timeouts

Upvotes: 1

Views: 2289

Answers (3)

HMR
HMR

Reputation: 39260

You could wrap your timeouts in an object or re use timeoutID for the second timeout.

Wrap in an object:

function Timer(){
  var me=this;
  this.currentTimerID=setTimeout(function(){
    console.log("First timeout");
    me.currentTimerID=setTimeout(function(){
      console.log("Second timeout");
    },100);
  },100);
};
Timer.prototype.cancel=function(){
  clearTimeout(this.currentTimerID);
};

var t = new Timer();//let this run it's course
setTimeout(function(){t = new Timer()},250);//start timer again
setTimeout(function(){t.cancel();},400);// cancel it after the first timeout

Re use timeoutID:

var timeoutID = setTimeout(
    function(){
        console.log("first event can be stopped with clearTimout(timeoutID)");
        timeoutID=setTimeout(function(){console.log("but not this one")}, 100)
    }, 100)
setTimeout(function(){
  clearTimeout(timeoutID);
},150);// will not execute the second timeout

One tip: If you're testing code with timeout then don't use such high values as it'll take 10 seconds for your original code to run.

Upvotes: 0

ced-b
ced-b

Reputation: 4065

You would have to create an array of timeout IDs such as this:

var timeoutIds = [];

timeoutIds.push(setTimeout(
  function(){
    console.log("first event can be stopped with clearTimout(timeoutID)");
    timeoutIds.push(setTimeout(function(){console.log("but not this one")}, 5000));
 }, 5000))

And then to clear:

for (int i = 0; i < timeoutIds.length; i++)
{
   clearTimeout(timeoutIds[i]);
}

timeoutIds  = [];

Upvotes: 1

Teemu
Teemu

Reputation: 23396

You can put the inner timeout into a variable too:

var innerTimeout,
    timeoutID = setTimeout(
    function(){
        console.log("first event can be stopped with clearTimout(timeoutID)");
        innerTimeout = setTimeout(function(){console.log("but not this one")}, 5000);
    }, 5000);

Upvotes: 3

Related Questions