views:

1216

answers:

4

Hello,

my problem is that I can not stop a timer.

I had this method to set a timeout from this forum. It supposed to store the identifyer in the global variable. By accident, I found out that it is still running after I hide "mydiv".

I also need to know now, if the recursive function creates multiple instances or just one for the timeouts. Because first I thought that it overwrites "var mytimer" everytime. Now I am not so sure.

What would be a solid way to stop the timer??

var updatetimer= function () {
//do stuff
     setTimeout(function (){updatetimer();}, 10000);

}//end function


//this should start and stop the timer
$("#mybutton").click(function(e) { 
       e.preventDefault();
      if($('#mydiv').is(':visible')){
                   $('#mydiv').fadeOut('normal');
          clearTimeout(updatetimer);

     }else{
                   $('#mydiv').fadeIn('normal');
                   updatetimer();
               }
});

thanks, Richard

+3  A: 

I think you misunderstand 'setTimeout' and 'clearTimeout'.

If you want to set a timer that you want to cancel later, do something like:

foo = setTimeout(function, time);

then call

clearTimeout(foo);

if you want to cancel that timer.

Hope this helps!

ylebre
I'd say it was pretty bad - it's functional, but there's no way to cancel it (because the value of setTimeout is not captured), but that's easily fixed and trivial compared to making a request every second. That's really excessive, imho.
annakata
thanks, now I don't understand my own code anymore. What is the advantage off using those anonymous functions anyway???see the link
that's a whole other question because the answer is rather wide-ranging :)
annakata
the best way the I think really,really simpel is to just do cleartimeout(foo)foo=settimeout(function,10000) in that recursive function.recursive in the way that it keeps calling it self caused by the timer.
is there maybe one plausible reason (in short) to use those anonymous functions like in the link provided and my code.Otherwise forget it. I won't use it then.
+1  A: 

As written mytimer is a function which never has the value of a timeout identifier, therefore your clearTimeout statement will achieve nothing.

I don't see any recursion here at all, but you need to store the value setTimeout returns you, and if you need to pair this with multiple potential events you need to store it against a key value you can lookup - something like an element id perhaps?

annakata
I understand what you are saying.
A: 

As noted above, the main reason why this code isn't working is that you're passingt he wrong thing into the clearTimeout call - you need to store the return value of the setTimeout call you make in updateFunction and pass this into clearTimeout, instead of the function reference itself.

As a second suggestion for improvement - whenever you have what you call a recursive timeout function, you would be better off using the setInterval method, which runs a function at regular intervals until cancelled. This will achieve the same thing you're trying to do with your updateFunction method, but it's cleaner as you only need to include the "do stuff" logic in the deferred function, and it's probably more performant as you won't be creating nested closures. Plus it's The Right way to do it which has got to count for something, right? :-)

Andrzej Doyle
From the discussion at http://stackoverflow.com/questions/729921/settimeout-or-setinterval , setInterval is not always better.
billyswong
yes, from that discussion alone, you get the notion that it tends towards using timeout as the prefered method. because setinterval quees up for example. I don't know about nested closures. Maybe you are right about that.
+1  A: 

I think that most people are getting at the reason why this isn't working, but I thought I would provide you with updated code. It is pretty much the same as yours, except that it assigns the timeout to a variable so that it can be cleared.

Also, the anonymous function in a setTimeout is great, if you want to run logic inline, change the value of 'this' inside the function, or pass parameters into a function. If you just want to call a function, it is sufficient to pass the name of the function as the first parameter.

var timer = null; 

var updatetimer = function () {
    //do stuff

    // By the way, can just pass in the function name instead of an anonymous
    // function unless if you want to pass parameters or change the value of 'this'
    timer = setTimeout(updatetimer, 10000);
};

//this should start and stop the timer
$("#mybutton").click(function(e) { 
     e.preventDefault();
     if($('#mydiv').is(':visible')){
     $('#mydiv').fadeOut('normal');
     clearTimeout(timer);  // Since the timeout is assigned to a variable, we can successfully clear it now

    } else{
     $('#mydiv').fadeIn('normal');
     updatetimer();
   }
});
Brian Grinstead