Why clearInterval is not working in my script? - javascript

I have got a problem with my clearInterval method.
I learn about JS in depth at FrontendMasters and there is an exercise where you need to use setInterval and log a string at every second and then run clearInterval after 5 seconds. I have access to the right solution but I would like to know why my solution is not working to get better understanding. The console.log('clear called', func); runs after 5 seconds and log the clear called string and the function body. I have tried to use setTimeout to wrap wrapper.stop() but it did not work that way either. I have used closures to try to solve the exercise. Here is my script.
function sayHowdy() {
console.log('Howdy');
}
function everyXsecsForYsecs(func, interval, totalTime) {
function clear() {
console.log('clear called', func);
clearInterval(func);
}
return {
start() {
setInterval(func, interval);
},
stop() {
setTimeout(clear, totalTime);
}
}
}
const wrapper = everyXsecsForYsecs(sayHowdy, 1000, 5000);
wrapper.start();
wrapper.stop();
Thanks

clearInterval does not take a function but a timer id which gets returned when using setInterval (so that you can set multiple timers onto the same function, and cancel them individually). To use that, declare a local variable inside everyXsecsForYsecs
var timer;
Then assign the timer to it:
timer = setInterval(func, interval);
Then you can clearInterval(timer).

Related

call function periodically in javascript until finished, then start calling different function

I have two functions on my page that I need to call periodically, but in a certain way only.
function_a needs to be run periodically when the page loads, until data is available and downloaded.
After this point, function_b then needs to run periodically forever.
I can easily do...
setInterval(function_a, 1000);
setInterval(function_b, 5000);
But this will run both functions from the start of page load and forever.
How can I stop function_a running once I have determined that it is not needed anymore, and only start function_b running after this point?
I can put checks within the function_a and function_b code so that they dont execute if not needed, but it seems very wasteful to still call them continually when they are not needed.
function_a(){
if (needed) { code here... }
}
function_b(){
if (needed) { code here... }
}
There must be a better way than that?
Instead of a setInterval here, setTimeout will work far better.
function a() {
//do stuff
if(condition) setTimeout(b, 5000)
else setTimeout(a, 1000)
}
function b(){
//do stuff
setTimeout(b, 5000)
}
a()
This way, the function will execute and schedule itself to run again on the desired interval. This is similar to the way requestAnimationFrame is used for creating animations.
You can assign a variable to setInterval() call and use clearInterval()
let a = setInterval(function_a, 1000);
function_b() {
if (a_is_not_needed) { clearInterval(a) }
}
Use clearInterval() to stop a function called in a setInterval()
var needed = false;
var f1 = function(){
console.log("Fct1");
if(needed){
setInterval(f2, 5000); // start f2 when f1 is finish
clearInterval(interval); // stop to call periodically f1
}
}
var f2 = function(){
console.log("Fct2");
}
var interval = setInterval(f1, 1000);
Try this fiddle and open console to see the result

Calling a function by an interval in a function called by interval JS

I want to call a function that could check an amount of time constantly using an interval within function that already works (running function) by interval.
That what I had did:
var interval;
var time = prompt("Insert amount of time in seconds");
function log ()
{
console.log ("log() called.");
}
function onrunning ()
{
interval = setInterval(log,time*1000);
}
gameloop = setInterval(onrunning,5);//This interval must not cleared
The first amount of time works fine but after that it's keep calling the log() function faster and faster till the browser crashes.
I tried to do this
var interval;
var time = prompt("Insert amount of time in seconds");
function log ()
{
console.log ("log() called.");
}
function onrunning ()
{
interval = setInterval(log,time*1000);
}
gameloop = setInterval(onrunning,5);
clearInterval(interval); //tried this but no differece.
You are clearing interval in a wrong place.
In your code, you are trying to clear it before it has been created (so it's basically a no-op).
You want to clear it after it has been created and executed:
function log ()
{
console.log ("log() called.");
clearInterval(interval);
}
You should also notice that since your onrunning is also fired as an "interval" callback, you are creating new log intervals on each callback execution frame. If you want to clear this interval too, just replicate the same logic as presented above, but inside onrunning callback.
I assume you want to fire the "log" callback ("onrunning" callback as well, probably) only once after a set period of time. In that case, you should use setTimeout instead of setInterval.
This has been already pointed out by Jaromanda X in this comment.

Recursive setInterval() runs continuously

I'm trying to run a function every 5 seconds using JavaScript using a recursive setInterval function.
The following code just logs "started" as fast as possible and then crashes the browser. Why is this not running every 5 seconds?
function five() {
console.log("five");
setInterval(five(), 5000);
}
five();
Don't use setInterval this way. Use setTimeout. By calling setInterval, you create a UNIQUE timer every time the function is called. SetTimeout would create one timer that ends, and then creates a new timer.
You should also change the way you reference five. five() executes the function immediately. Just five passes a function reference, so do it as you see below.
function five() {
console.log("five");
setTimeout(five, 5000);
}
five();
Of course, you can always pass the function call as a string to be evaluated:
setTimeout("five()", 5000); // note the quotes
But this is generally considered bad practice.
You're calling five immediately, instead of merely passing it in:
function five () {
console.log("five");
}
setInterval(five, 5000);
/* ^ */
Change this line:
setInterval(five(), 5000);
like this:
setInterval(five, 5000);
But seems like what you really need is:
setTimeout(five, 5000);
So your code will look like:
function five() {
console.log("five");
setTimeout(five, 5000);
}
five();
The reason of crashing it is that you are calling the function five. Instead of that you should pass it as parameter.
setInterval(five, 5000);

setTimeOut() or setInterval() . 4 methods to apply same thing. which is best?

I am displaying a countdown watch with respect to a given endtime.
although its working perfect but i want to know which is best methods to apply.
below is my countdown function.
var timerId;
var postData = {endDate : endDate, tz : tz};
var countdown = function()
{
$.ajax({
type : 'post',
async : false,
timeout : 1000,
url : './ajax_countdown.php',
data : $.param(postData),
dataType : 'json',
success : function (resp){
$('#currentTime').html(resp.remainingTime);
}
});
}
what i want is that function (countdown) shoud be called automatically after every 1 second and if it does not execute/completed within 1 second then cancel the current ajax and start a new ajax call.
now I found there are 4 working methods
method 1: using setInterval() with window object
window.setInterval(countdown, 1000);
method 2 : using setInterval() independently
setInterval(function() {countdown()}, 1000);
method 3 : using setTimeOut inside the function an call other function to intialize main function
var countdown = function() {
$.ajax({ //ajax code });
timerId = setTimeout(countdown, 5000); // assign to a variable
}
function clockStart() {
if (timerId) return
countdown();
}
clockStart(); // calling this function
method 4 : using anonymous function call
var countdown = function() {
$.ajax({ //ajax code });
timerId = setTimeout(countdown, 5000);
}
(function(){
if (timerId) return;
countdown();
})();
Please tell me
What is con and pro of each method and which one is best/right method?
Should i use clearTimeOut() or clearInterval() ?
References
http://javascript.info/tutorial/settimeout-setinterval
Calling a function every 60 seconds
http://www.electrictoolbox.com/using-settimeout-javascript/
I wouldn't use any of your methods. The reason is setTimeout and setInterval do not guarantee that your code will execute after the specified delay. This is because JavaScript is single threaded.
If I need to call a function only once after a specified delay then I use setTimeout. However if I need to call a function after a fixed interval of time then I do not use setInterval. Instead I make use of delta timing. Here's the code.
The advantage of using delta timing is that your code will execute closer to the fixed interval of time you specify. It corrects itself. Creating and using a delta timer is simple. For example your code would be written as follows:
var timer = new DeltaTimer(function (time) {
$.ajax({
// properties
});
if (time - start >= 5000) timer.stop();
}, 1000);
var start = timer.start();
The above delta timer is better than setInterval (method 1), makes use of setTimeout (method 2) but also corrects itself, starts the timer using a function (method 3), and doesn't pollute the scope with a special clockStart function (method 4).
In addition you can easily get the exact time the function is called after the timer starts as the time the function is called is passed as an argument to the function. The timer also has a stop method to stop the timer. To start it again call start again.
Edit:
If you want to make the DeltaTimer look more like setInterval (start the timer automatically) you may implement a spawn function as follows:
DeltaTimer.spawn = function (render, interval) {
var timer = new DeltaTimer(render, interval);
var start = timer.start = function (start) {
return function () {
render.start = start();
};
}(timer.start);
start();
return timer;
};
Then you may automatically create and start the DeltaTimer as follows:
var timer = DeltaTimer.spawn(function countdown(time) {
$.ajax({
// properties
});
if (time - countdown.start >= 5000) timer.stop();
}, 1000);
Thus var timer = DeltaTimer.spawn(funct, delay); is equivalent to var interval = setInterval(funct, delay); and timer.stop(); is equivalent to clearInterval(interval);. I guess that's as much as you can automate it.
The benefit of using #1 over #2 is that the window reference removes the chance of a scope variable overwriting setInterval.
// When out of global scope...
function setInterval() {
}
window.setInterval(foo, 100); // still calls the "correct" setInterval
There's no difference between wrapping the call to countdown in a function (#1, #2). #2 gives you greater flexibility as you can also call other functions/ pass arguments etc (although it's obviously trivial to swap from #1 to #2 if this becomes the case).
#4 saves you having to declare a function clockStart, other than that, it's the same as #3.
Use clearTimeout if you used setTimeout, and clearInterval if you used setInterval...
You should also be aware of how setTimeout and setInterval work differently. There's an amazing answer here which explains that...
As for what I'd use? I'd use #2.
if you are creating countdown then why u don't use jquery plugin and customize it according to your requirements? Checkout here
http://www.tripwiremagazine.com/2012/05/jquery-countdown-scripts.html

stop settimeout in recursive function

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
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();
}
});
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!
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?
This is a simple pseudocode for controlling and conditioning recursive setTimeout functions.
const myVar = setTimeout(function myIdentifier() {
// some code
if (condition) {
clearTimeout(myIdentifier)
} else {
setTimeout(myIdentifier, delay); //delay is a value in ms.
}
}, delay);
You can not stop all the functions that are created, intead of that convert the function to setInterval (represent the same logic that your recursive function) and stop it:
// recursive
var timer= function () {
// do stuff
setTimeout(function (){timer();}, 10000);
}
The same logic using setInterval:
// same logic executing stuff in 10 seconds loop
var timer = setInterval(function(){// do stuff}, 10000)
Stop it:
clearInterval(timer);
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? :-)
(function(){
$('#my_div').css('background-color', 'red');
$('#my_div').hover(function(){
var id=setTimeout(function() {
$('#my_div').css('background-color', 'green');
}, 2000);
var id=setTimeout(function() {
$('#my_div').css('background-color', 'blue');
}, 4000);
var id=setTimeout(function() {
$('#my_div').css('background-color', 'pink');
}, 6000);
})
$("#my_div").click(function(){
clearTimeout(id);
})
})();

Categories

Resources