setinterval causing my app to crash - javascript

Can anyone explain why this is causing my app to crash? It always crashes on the second iteration of the loop.
function FetchMetaData () {
alert("Am I being fired");
}
var timer= setInterval(FetchMetaData(),10000);

It's not "crashing"; you're just calling the function once. You should pass the function itself to setInterval(), not the result of calling the function:
var timer = setInterval(FetchMetaData, 10000);
When you write it as FetchMeData(), that means that the function should be called right then and there, and that whatever value it returns should be what's passed to setInterval(). Sometimes that makes sense, but in this case you need to pass a reference to your function. You do that in JavaScript by simply using the name of the function without calling it.

Related

Safely clear JavaScript timeout

I have created a JavaScript function that does the following:
function myFunction() {
DoStuff;
watch = setTimeout(myFunction, 1000);
}
where
watch
is a global variable initially set to null.
Then, I have a second function, that can be called at any moment, of the form:
function mySecond() {
DoStuff;
clearTimeout(watch);
}
Now, it happens sometimes that, although the second function is called and the timeout is somehow cleared, the first function is called another time. I guess this is happening because when the second function is called, a request for the first function has already been sent, and thus the timer works another time, and keeps calling itself over and over... I would like to point out that this does not happen always, I guess it depends on a specific timing condition you can encounter.
How to safely remove ALL the possibilities that the first function is called again?
Problem with this code is watch holds the last timeout only. This should fix it
function myFunction() {
DoStuff;
if (watch) { clearTimeout(watch); }
watch = setTimeout(myFunction, 1000);
}

why setTimeout dont work in my code? I need workable code)

I dont know why my code dont work. Please help!
$('nav').mouseout(setTimeout(function() {
$(this).removeClass('subm')
}, 1000));
Without setTimeout is work normaly.
setTimeout(...) is being called immediately. It returns the id number of the newly pending timeout. The timeout is only registered and called once here. The execution of your code is happening like this:
setTimeout(function() {
$(this).removeClass('subm')
}, 1000);
// = 2
$('nav').mouseout(2);
You need to pass .mouseout() a function that calls setTimeout each time. You also need to fix the this reference, which is different inside the setTimeout callback. This should fix both issues:
$('nav').mouseout(function() {
var self = this;
setTimeout(function() {
$(self).removeClass('subm')
}, 1000);
});
In javascript, like in most other languages, when you do this:
variable = some_function();
you're passing the return value of a function to a variable. Similarly when you do this:
a_function(another_function());
you're passing the return value of another function as an argument to a function.
This works the same in javascript, C, PHP, Ruby and even Fortran.
So, when you do this:
$('nav').mouseout(setTimeout(..));
You're passing the return value of setTimeout as an argument to mouseout. And setTimeout returns a number which can be used in clearTimeout. So you're basically doing this:
$('nav').mouseout(a_number);
What you want instead is to pass a function:
$('nav').mouseout(function(){setTimeout(..)});
Or if you find that hard to read then do this:
function handleMouseOut () {
setTimeout(...);
}
$('nav').mouseout(handleMouseOut); // note we're passing a function here
// not calling it

Pause JavaScript - setTime

I have created a JavaScript version of the Little Man Computer based on the Java one at http://www.atkinson.yorku.ca/~sychen/research/LMC/LMCHome.html
I have it working in by stepping through each instruction. I have a function called stepCode() that does this.
What I want is a function that will run the program, pausing for a second between each step until the simulated program ends.
The code I have is this:
function runProgram()
{
var milliseconds = 1000;
var timeOut;
programRunning = true;
while(programRunning)
{
timeOut = setTimeOut(stepCode(), milliseconds);
}
}
This seems does not work. It still performs all the stepCode() calls one after the other very quickly. I want to pause between each stepCode() call.
I'm obviously doing something wrong. Any ideas?
You should use setInterval instead of setTimeout. Additionally, you need to reference the function, not call the function:
var timeOut; // global timeout variable to ensure both methods have access to it.
function runProgram() {
var milliseconds = 1000;
timeOut = setInterval(stepCode, milliseconds); // use setInterval instead of setTimeout
}
function stepCode {
// ... code processing here ...
// I assume you are setting programRunning to false at some point in this method.
// Instead of setting programRunning = false, you would do:
clearInterval(timeOut);
// Note, if you only have one timeout interval set, you can use clearInterval();
}
setInterval will cause the stepCode function to run every 'milliseconds' until you call clearInterval(timeOut);; setTimeout will only queue it up once. Anything that is queued via setTimeout will not execute until the current flow of code has been completed. As a result, programRunning will run and queue up several setTimeout executions. Once the programRunning variable hit false, the current code flow will finish and ALL of the queues will wait 1 second, and effectively execute all at the same time, or in rapid succession.
When you pass in a method call (e.g. stepCode()), it will call the method. You have to pass a reference to the function stepCode (notice no parens), to ensure that it knows what to run each time it executes.
This Fiddle Demo simulates a counter, which is common thing people attempt to execute using setInterval. It demonstrates the basic concept and use of setInterval.
In addition to suggested setInterval use that will call stepCode at 1 second intervals until cleared (or until the page is reloaded), and correction of removing () after stepCode that results in immediate stepCode executon, you can still use setTimeout if they are chained as shown below. Depending on what stepCode does and how long it takes, this solution has an advantage of ensuring that there is 1 second of idle time between the end of the previous and the beginning of the next stepCodes.
var milliseconds = 1000;
function runProgram()
{
programRunning = true;
stepCodeWrapper();
}
function stepCodeWrapper() {
if (programRunning) {
stepCode();
setTimeOut(stepCodeWrapper, milliseconds);
}
}
Just try with:
timeOut = setInterval(stepCode, milliseconds);
Bic, thanks for your swift response. You are correct about the programRunning flag being set to false inside the stepCode() function. I've set it as a global variable so that I could possibly halt the program by pressing a button, but thats another problem.
Tried both setInterval and setTimeout. You are right about it repeatedly calling the function. Using either method locks up the browser with repeated function calls. This is probably as its in a while loop. I cannot think of another was to repeatedly call the stepCode() function otherwise.
I sort of understand the difference between setInterval & setTimeout. Thanks, and I understand that would make the while loop redundant, but then how to stop it calling the stepCode function when the programRunning flag is set to false?

Function calling itself not working (infinite loop, Javascript)

I'm trying to wait and then get a message when all images in an array have completed loading (using .complete), per the answer here. As such I set up an infinite loop like the below. however, when I run this I get an error that checkForAllImagesLoaded() is not defined. This code is being run through a bookmarklet, and as such it's all wrapped up in an anonymous function construct (as below). If I re-define my function and variable outside of that construct, it works. But that seems to be a poor way to write a bookmarklet. How can I fix this so it will still recognize the function after the setTimeout?
(function() {
//var images = array of images that have started loading
function checkForAllImagesLoaded(){
for (var i = 0; i < images.length; i++) {
if (!images[i].complete) {
setTimeout('checkForAllImagesLoaded()', 20);
return;
}
}
}
checkForAllImagesLoaded();
})();
Remove the function call, and take out the quotes. If you don't put the quotes, setTimeout gets a direct reference to the function which it can invoke later. However, if inside a string such as "checkForAllImagesLoaded" or "checkForAllImagesLoaded()", then it will execute the code passed-in when the timeout occurs.
At that time, checkForAllImagesLoaded will be searched for in the global object (window) but it is not defined there, reason being why you're getting the undefined error.
Your code is wrapped in a self-calling anonymous function, and outside of it checkForAllImagesLoaded does not exist. So pass a direct reference to the function in your setTimeout call, instead of a string.
setTimeout(checkForAllImagesLoaded, 20);
setTimeout can be called with either a function (and optional arguments), or a string containing JavaScript code:
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
var timeoutID = window.setTimeout(code, delay);
Remove the () in the settimeout call.
setTimeout('checkForAllImagesLoaded', 20);
With your code, you set a number of timeouts per call. You should just set the timeout once per checkForAllImagesLoaded() call and perhaps increase the waiting period (20 milliseconds is just too quick). E.g.
function checkForAllImagesLoaded() {
var allComplete=true;
var i=0;
while (i<images.length && allComplete) {
allComplete=images[i++].complete;
}
if (!allComplete) { // Any incomplete images?
setTimeout('checkForAllImagesLoaded()',1000); // Wait a second!
}
}

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