I was trying to implement a simple news ticker for a website I am creating.
Being new to JS and JQuery, I got the code off a website. The code works perfectly fine, but a too much recursion (firefox) error occurs when I shift the function call.
Original function:
$(document).ready(function(){
var tick=function()
{
window.setTimeout(function()
{
$('#ticker li:first').animate({marginTop:"-30px"},700,function()
{
$(this).detach().appendTo('#ticker').removeAttr('style');
});
tick();//Old position for function call- works fine
},4000);
};
tick();
});
The above code works, but when I shift the recursive call to outside the setTimeout function, the a recursion error. Slightly altered code:
$(document).ready(function(){
var tick=function()
{
window.setTimeout(function()
{
$('#ticker li:first').animate({marginTop:"-30px"},700,function()
{
$(this).detach().appendTo('#ticker').removeAttr('style');
});
},4000);
tick();//New position for function call-leads to unresponsive page
};
tick();
});
My question is this : shouldn't both the above codes works in the exact same manner? What changes when the location changes?
The purpose of the setTimeout function is to set another function to run after a specified amount of time. However, the timeout runs without blocking other code from executing -- the setTimeout function only sets the timeout, it executes immediately rather than waiting for the function passed to it to actually run. When you have the tick() call inside the setTimeout function call with a timeout of 4000 ms, you get the effect of rerunning the tick() every four seconds. However, once you move it outside the setTimeout call, it's rerunning instantly and infinitely as soon as you call it the first time.
In the first case, tick() doesn't call itself until the timer stops because the call to itself resides within the setTimeout() function. In the second case, tick() is instantly calling itself, with no timeout in between. This will call itself infinite times and if the browser didn't give you the recursion error and allowed it to continue, it would lock up or crash the browser eventually.
To show that, the second case can be simplified to:
var tick=function(){
tick();
};
tick();
You are simply moving the tick() inside the setTimeout. Here's your new code. If you don't do this, tick() will be called immediately.
$(document).ready(function(){
var tick=function()
{
window.setTimeout(function()
{
$('#ticker li:first').animate({marginTop:"-30px"},700,function()
{
$(this).detach().appendTo('#ticker').removeAttr('style');
});
tick();//New position for function call-leads to unresponsive page
},4000);
};
tick();
});
Related
Hey i am creating a DOM javascript library and i found myself having the following problem:
For example, if i take a function lets say function update() how can i check if this function has been created on another file; If it has been created on another file how can I make it run once or every couple of seconds without the user need to do this?
For example in the library p5.js :
//If this function has created on this file it will run every one second
function update(){
}
&&
//if this function has created on this file it will call itself once the page is loaded
function start(){
}
*Edit: tried to be more clear on my question thank you for your answers!
Instead of the user needing to call setInterval() to repeat update(), it can call it itself.
function update() {
setInterval(function() {
// do something
}, 1000);
}
All the actual work that needs to be done goes where // do something is.
setTimeout(func, 1000) will call func 1000 milliseconds later.
If you wanted your function to call immediately, you could do a recursion (bad way, better use a loop, but it's useful to illustrate the next example):
// calls itself infinitely, without any delay
function update(){
update(); // Will cause a stack overflow, infinitely deep recursion
}
Now you can make use of setTimeout and tell update to run a second later.
// calls itself infinitely, 1 second delay between calls
function update(){
setTimeout(update, 1000);
}
There is no recursion here. Instead, you defer the call to update() for one second. The second time update() is called, another setTimeout will be called, and so on infinitely.
The second part of your question:
//call itself once the page is loaded
function start(){
}
You can set an event listener to when the page is loaded, and call that function:
window.addEventListener('load', start);
Do this right after defining start().
To reflect your comment:
If you want to detect if the global function update has been defined (by the user, probably) and want to start calling it automatically on equal intervals of 1 second, you'll need to check its existance with typeof and then apply setInterval on it:
if(typeof update === "function") {
setInterval(update, 1000);
}
To make it explicit that you're refering to a global update and not a local variable, you can use window.update instead. In that case, you could also check if it exists this way:
if(update in window)
I want to call a function in JavaScript continuously, for example each 5 seconds until a cancel event.
I tried to use setTimeout and call it in my function
function init()
{ setTimeout(init, 5000);
// do sthg
}
my problem is that the calls stops after like 2 min and my program is a little bit longer like 5 min.
How can i keep calling my function as long as i want to.
thanks in advance
The only conceivable explanations of the behavior you describe are that:
As another poster mentioned, init is somehow getting overwritten in the course of executing itself, in the // do sthg portion of your code
The page is being reloaded.
The //do sthg code is going into some kind of error state which makes it looks as if it not executing.
To guarantee that init is not modified, try passing the // do sthg part as a function which we will call callback:
function startLoop(callback, ms) {
(function loop() {
if (cancel) return;
setTimeout(loop, ms);
callback();
}());
}
Other posters have suggested using setInterval. That's fine, but there's
nothing fundamentally wrong with setting up repeating actions using setTimeout with the function itself issuing the next setTimeout as you are doing. it's a common, well-accepted alternative to setting up repeating actions. Among other advantages, it permits the subsequent timeouts to be tuned in terms of their behavior, especially the timeout interval, if that's an issue. If the code were to be rewritten using requestAnimationFrame, as it probably should be, then there is no alternative but to issue the next request within the callback, because requestAnimationFrame has no setInterval analog.
That function is called setInterval.
var interval = setInterval(init, 5000);
// to cancel
clearInterval(interval);
I'm not 100% sure how setTimeout works in JavaScript. Say I have something like this:
$(document).ready(function() {
testTimeout();
});
function testTimeout() {
alert("testing timeout");
setTimeout(testTimeout, 5000);
}
This would display a popup window every 5 after the page is ready. What would happen if then I called testTimeout from a button click?
$("#button").click(function() {
testTimeout();
});
Would the button click call testTimeout and add another timeout every 5 seconds? Or, would the button click reset the timeout from when the button was pressed? The reason I am asking is because I would like to design something like this where I can pass a parameter to my timeout function. When the web page starts up, I have a default parameter. However, if I press a button, I would like my timeout function to be called right away and every 5 seconds after with my new parameter. But, I don't want the timeout function with the old parameter to continue repeating. How can I achieve this? Any help and understanding would be greatly appreciated.
This would display a popup window every 5 after the page is ready.
No it wouldn't, it would show an alert repeatedly with no delay and/or cause a "too much recursion" error, because setTimeout(testTimeout(), 5000) calls testTimeout and passes its return value into setTimeout, just like foo(bar()) calls bar and passes its return value into foo.
If you remove the ():
function testTimeout() {
alert("testing timeout");
setTimeout(testTimeout, 5000);
// here --------------^
}
Then it would do that.
What would happen if then I called testTimeout from a button click?
You'd end up with the function being called twice as often (more than once every 5 seconds), because every time you call it, it reschedules itself. A third time would make it more frequently still (three times/second), and so on.
If you want to avoid that, one option is to remember the timer handle and cancel any outstanding timed callback if you call the function before then:
var handle = 0;
function testTimeout() {
clearTimeout(handle); // Clears the timed call if we're being called beforehand
alert("testing timeout");
handle = setTimeout(testTimeout, 5000);
}
(I initialized handle with 0 because calling clearTimeout with a 0 is a no-op.)
Have you tried to asign variable to your setinterval;
var foo = setTimeout(testTimeout(), 5000);
and then when right event comes just destroy that variable.
clearInterval(foo);
And now you can asign it again...
In your case it would simply repeat endlessly, because you're executing the function instead of passing the reference. You should do it like this:
function testTimeout() {
alert("testing timeout)";
setTimeout(testTimeout, 5000);
}
Note the missing braces after testTimeout. This tells setTimeout to execute that function, instead of the result of that function, which is how your original code behaved.
" I would like my timeout function to be called right away and every 5 seconds after with my new parameter. But, I don't want the timeout function with the old parameter to continue repeating "
In order to achieve what you're trying to do you should remove the timeout:
var timeoutId;
function testTimeout() {
alert("testing timeout)";
clearTimeout(timeoutId );
timeoutId = setTimeout(testTimeout, 5000);
}
Notes:
You can stop the previous timeoutI from firing by catching the id returned from the setTimeout method and passing that to the clearTimeout method
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?
I have a java script function that i have called on body load mousemove() the function is working but the problem is that function is not overloading. Here is the code:
function timeout(){
setTimeout ("logout()",60000);
}
function logout()
{
parent.parent.location="logout.php";
}
<body onmousemove="timeout()" >
now the problem is it calls on body load and whenever mouse moves but the page still move to the logout page after the specified time however it should override the time whenever mouse moves and the function calls.
Each time you call setTimeout it adds another call to the queue. In other words, you aren't replacing the current timeout. To fix it, you will need to cancel the existing timeout event before you start another one by calling clearTimeout with the value of the previous call to setTimeout.
var timeoutID = null;
function timeout() {
if (timeoutID !== null) {
clearTimeout(timeoutID);
}
timeoutID = setTimeout(logout, 60000);
}
I also changed the call to setTimeout to pass a reference to the logout function instead of a string. It's best to avoid passing a string since it uses eval and isn't necessary.