suspend setInterval - javascript

I use setInterval to run a function (doing AJAX stuff) every few seconds. However I also have an other function also calling it.
setInterval(myFunc(), 5000);
function buttonClick() {
// do some stuff
myFunc();
}
Most of the time it works, however sometimes this function gets called twice at the same time resulting in receiving exactly the same result twice, something I don't want.
I think I have to use clearTimeout:
var interval = setInterval(myFunc(), 5000);
function buttonClick() {
clearTImeout(interval);
// do some stuff
myFunc();
interval = setInterval(myFunc(), 5000);
}
However this causes the function to halt. Since it gets called from an other function some code never gets executed. How can I prevent this?

however sometimes this function gets called twice at the same time resulting in receiving exactly the same result twice, something I don't want.
JavaScript on browsers is single-threaded (barring using the new web workers stuff, but that wouldn't apply here anyway). Your function will never get called while it's running. (But more below.)
In your various code quotes, you're calling myFunc where you mean to just be referring to it. E.g.:
var interval = setInterval(myFunc(), 5000);
should be
var interval = setInterval(myFunc, 5000);
// ^--- No parentheses
Your code cancelling the timeout will work if you correct that:
var interval = setInterval(myFunc, 5000);
function buttonClick() {
clearTImeout(interval);
// do some stuff
myFunc();
interval = setInterval(myFunc, 5000);
}
But there's no reason to do that, myFunc cannot get called while it's running anyway.
If myFunc is triggering something that will complete asynchronously (an ajax call, for instance), the above won't help (for the simple reason that myFunc will start the process and then return; the process will complete separately). In that situation, your best bet is to have myFunc schedule its next call itself:
function myFunc() {
// Do my work...
// Schedule my next run
setTimeout(myFunc, 5000);
}
...and not use setInterval at all.

I realize there's a couple of solutions already, but thought I'd show one that has a tad more than just "do this". I tend to learn by example, and thought I would extend the same practice. That being said, the demo is here but I'll try to explain as well.
// Here we assign the function to a variable that we can use as an argument to the
// setInterval method.
var work = function(){
// performing a very simple action for the sake of demo
$('#log').append('Executed.<br />');
};
// this is a variable that is essentially used to track if the interval is or is
// not already running. Before we start it, we check it. Before we end it, we also
// check it. Let's start off with it started though
var worker = setInterval(work, 5000);
// bind to the start button
$('#start').click(function(){
// Test: is the worker already running?
if (worker)
// Yes it is, don't try to call it again
$('#warn').text('Timer already running!');
else{
// no it's not, let's start it up using that function variable we declared
// earlier
worker = setInterval(work,3000);
$('#warn').text('Started!');
}
});
// bind to the stop button
$('#stop').click(function(){
// test: is the worker running?
if (!worker)
// no, so we can't stop it
$('#warn').text('Timer not running!');
else{
// yes it's working. Let's stop it and clear the variable.
clearInterval(worker);
worker = null;
$('#warn').text('Stopped.');
}
});

Unless myFunc returns a function I would do this (also use clearInterval in stead of clearTimeout):
var interval = setInterval(myFunc, 5000);
function buttonClick() {
clearInterval(interval);
// do some stuff
myFunc();
interval = setInterval(myFunc, 5000);
}
setInterval expects a function in its argument. You call a function by using myFunc(). so whatever is returned by myFunc was passed to setInterval which is probably not what you want.

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.

Javascript Delay

I understand that Javascript does not have a delay(500) method, which would delay execution for 500 milliseconds, so I have been trying to get around that by using setTimeout and setInterval.
for(var i =0; i< 10; i++){
/* Animation Code */
var doNothing = function(){var m =5;}
setTimeout(doNothing, 50);
}
However, this does not seem to work. I essentially want some code that stops the execution for n milliseconds and then continues execution.
Practically speaking, you can't do this. Deal with it and find a callback-based way instead. Typically this means putting everything that should happen after the delay in the callback itself.
For example, you can't do this to make baz wait:
foo();
setTimeout(function() {
bar();
}, 500);
baz();
so you do the only thing you can:
foo();
setTimeout(function() {
bar();
baz();
}, 500);
The setInterval() Method wait a specified number of milliseconds, and then execute a specified function, and it will continue to execute the function, once at every given time-interval.
Syntax
window.setInterval("javascript function",milliseconds);
The window.setInterval() method can be written without the window prefix.
The first parameter of setInterval() should be a function.
How to Stop the Execution?
The clearInterval() method is used to stop further executions of the function specified in the setInterval() method.
Syntax
window.clearInterval(intervalVariable)
The window.clearInterval() method can be written without the window prefix.
To be able to use the clearInterval() method, you must use a global variable when creating the interval method:
myVar=setInterval("javascript function",milliseconds);
Then you will be able to stop the execution by calling the clearInterval() method.
good refrence
If you came from the language/framework/API background, where you could suspend the execution with something like Sleep, or process user input synchronously with something like DoEvents, it won't work in JavaScript.
There is no way you can block the JavaScript event loop with something like this, for a good reason: UI responsiveness. In JavaScript, everything is asynchronous. You can use setTimeout to do something upon a timer event, but the user is still able to access the UI between the timer events or even navigate away from the page.
To address your code fragment, what you are looking for is called an asynchronous state machine. It allows to preserve the state of the code between stop/continue (in your case, it's the state of the animation, although i variable is also a part of it):
(function()
{
var i = 0;
var nextStep = function()
{
if (i<10)
{
/* Animation Code */
i++;
setTimeout(nextStep, 500);
}
}
nextStep();
})();
It will be much easier to code when all browsers support the new yield keyword:
http://pag.forbeslindesay.co.uk
On a side note, some other answers suggest using setInterval. There is a subtle but important difference between delay and interval. Delay is the time between two steps. Interval is the time since the previous step started. If each step of animation takes 200ms, and you use the interval of 500ms, the actual delay between two steps will be 300ms, not 500ms as probably expected.
setInterval() - executes a function, over and over again, at specified time intervals
To pass a function as a string, be sure to append the function name with parentheses.
window.setInterval("someFunction()", 5000);
When passing a function pointer, do not include the parentheses.
window.setInterval(someFunction, 5000);
var timer_id=setInterval(doNothing,500);
If you want to stop the execution
make the timer_id variable global
clearInterval(timer_id);
Much cleaner and readable code would be if you use RxJS
Here is an example:
Rx.Observable
.interval(1000)
.take(10)
.subscribe((x) => console.log(`${x}: ${new Date().toLocaleTimeString()}`))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.lite.min.js"></script>
interval - is a time delay between your animation calls. In my example
it's 1000ms
take - number of times to execute subscribe - is function
that will be called every 1000ms for 10 times (in your case it will be
your animation code)
Here some something that could help.
function delay( s , callback )
{
var fct_ref = "tmp_" + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 6).toUpperCase();
var tmp_fct = ( callback !== undefined ) ? callback.toString().match(/^[^{]+\{(.*?)\}$/)[1] : "";
document.getElementsByTagName("body")[0].insertAdjacentHTML("beforeend","<div id='"+fct_ref+"' style='background-color:transparent;color:transparent;position:absolute;top:"+window.scrollY+"px;left:"+window.scrollX+"px;opacity:1;transition:all "+s+"s'>-</div>");
var func = new Function("return function transition"+fct_ref+"(e){ e.target.removeEventListener('transitionend' , transition"+fct_ref+", false ); "+tmp_fct+" ; document.getElementById('"+fct_ref+"').parentNode.removeChild(document.getElementById('"+fct_ref+"')); };")();
document.getElementById(""+fct_ref).addEventListener("transitionend", func , false );
document.getElementById(""+fct_ref).offsetHeight;
document.getElementById(""+fct_ref).style.opacity="0";
}
delay(1, function() { console.log("ANIMATION_1"); } );
delay(3, function() { console.log("ANIMATION_3"); } );
delay(5, function() { console.log("ANIMATION_5"); } );

Javascript set/clearinterval is not working

How can i stop a interval in javascript?
why does the interval not stop?
setInterval(alarm, 500);
window.clearInterval(alarm);
also tried:
window.setInterval(alarm, 500);
window.clearInterval(alarm);
always the same problem :(
still doesn't work:
var switc = 1;
getValue();
function getValue (){
if(switc == 1){
var myTimer = window.setInterval(alarm, 500);
}
else if(switc == 0){
window.clearInterval(myTimer);
}
}
function alarm(){
console.log("test");
}
When you call setInterval it returns a integer that you use to cancel the event. Store that into a variable and use that variable to cancel the event.
var myTimer = window.setInterval(alarm, 500);
window.clearInterval(myTimer);
EDIT:
Your code does not work since myTimer is a local variable and is reset every single time you call the function!
Make it global.
var myTimer = null;
function getValue (){
if(switc == 1){
myTimer = window.setInterval(alarm, 500);
}
...
MDN Docs: window.setInterval
Calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.
Syntax
var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
var intervalID = window.setInterval(code, delay);
where
intervalID is a unique interval ID you can pass to clearInterval().
func is the function you want to be called repeatedly.
code in the alternate syntax, is a string of code you want to be executed repeatedly (using this syntax is not recommended for the same reasons as using eval())
delay is the number of milliseconds (thousandths of a second) that the setInterval() function should wait before each call to func. As with setTimeout, there is a minimum delay enforced.
Note that passing additional parameters to the function in the first syntax does not work in Internet Explorer. If you want to enable this functionality on that browser you must use a compatibility code (see the Callback arguments paragraph).
That code evinces a misunderstanding of the API. The setInterval() function takes two arguments: a function to call, and a number representing the number of milliseconds between calls. The function returns a token (a number) that identifies that particular interval timer. The token can be passed to clearInterval() to cancel the timer.
You are tring to clear an non existent interval. Assign the id returned by setInterval() to an variable and use it in clearInterval().
In your case alarm is the function that executes and its not the intervals id
var interval = setInterval(alarm, 500);
clearInterval(interval);
var timer = setInterval(alarm, 500);
Window.clearInterval(timer);
function alarm() {
// Do stuff
}
You need to save the handle of the interval to a variable so you can reference it later when you want to clear/stop it.

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