Here's a link with some sample code.
http://jsfiddle.net/4djNt/2/
I assumed, until I started testing, that the return value of a setTimeout() would be some kind of browser object.
In fact it seems to be a simple integer. I also believed that assigning the return value of setTimeout to a global variable would mean that there could only be one such object. But as you'll see if you click the "start timer" button more than one, there can be multiple timers running concurrently.
For instance
I click the start button
the script creates a timeout
it is timeout 1, due to fire in five seconds
one second later, I click again and now there's a timeout 2
now I have timeout 1 due to fire in four seconds and timeout 2 in five seconds
I click the stop button and only timeout 2 is cleared
The problem of user clicks creating multiple timers can be solved by always clearing the current timeout var before setting it. But I would really like to understand what Javascript is doing actually doing here.
setTimeout and setInterval return a number. The number is the id of the timer. Active timers can be stopped using clearTimeout and clearInterval respectively.
If you lose the timer's id, you'd either have to guess it again, or wait for it to complete (assuming it's a timeout).
If the timer hasn't been cancelled in the number of milliseconds specified in the delay parameter, it will execute the callback function in the global context.
The return value of setTimeout can be passed to clearTimeout to prevent a scheduled task from running. If the variable has been set and your button is pushed again, run clearTimeout first, then setTimeout assuming you want only the 2nd push to schedule.
The questioner asks only about timeout objects, which are returned in lieu of numbers in some environments, for instance timeoutObject. For purposes of canceling the callback, passing the entire timeout object to clearTimeout(toObj) does the trick.
{
called : bool
_idleTimeout : null
_idlePrev : null
_idleNext : null
_idleStart : null
_onTimeout : function (){}
_repeat : null
unref : function () {}
ref : function () {}
close : function () {}
}
Related
Please go through below code ,
<button onclick="myVar = setTimeout(myFunction, 3000)">Try it</button>
When the button is clicked , it display my function ; but myVar variable is assigned to a function and myVar is not called again, how does it execute it ?
Complete code in below link
https://www.w3schools.com/js/tryit.asp?filename=tryjs_settimeout2
Clicking the button runs the setTimeout function, which starts a timer inside Javascript
When you run setTimeout, with the name of a function and a number of milliseconds, it starts an internal timer in Javascript.
You do not have to do anything to later trigger that function: Javascript will automatically do so, once the time is up (or as soon as possible afterwards, if Javascript is busy).
Here is your original version (shortened):
function myFunction() {
alert("Hello");
}
<h2>JavaScript Timing</h2>
<p>After you click "Try it", you will get an alert after 3 seconds, UNLESS you click "Cancel" during that time.</p>
<button onclick="myVar = setTimeout(myFunction, 3000)">Try it</button>
<button onclick="clearTimeout(myVar)">Cancel</button>
Showing that you don't need the "myVar="
You only needed the myVar= because you wanted to be able to cancel the timer. When you call setTimeout, it (immediately) returns a handle to the timer. You can use that handle to cancel the timer.
If you don't need the ability to cancel, you don't need the myVar=. Just call setTimeout, like this:
function myFunction() {
alert("Hello");
}
<h2>JavaScript Timing</h2>
<p>After you click "Try it", you will get an alert after 3 seconds.</p>
<button onclick="setTimeout(myFunction, 3000)">Try it</button>
Showing that you don't even need the separate Javascript function
setTimeout can be given a full definition of a function, rather than just a name.
<button onclick="setTimeout(function(){alert('Hello')}, 3000)">Try it</button>
How setTimeout works
Javascript maintains a list of things that it has been asked to do at intervals (with setInterval) or at particular times (with setTimeout).
It generally gets on with the program it is running, but eventually runs out of things to do. Then it starts going through those lists of pending tasks, to see if enough time has passed for them to be ready to execute.
This process, called the "event loop" is quite complicated. Fortunately we don't have to worry about it, other than bear in mind that it is not magic. If we have a program that requires a long run of processing, say 1 minute, then during that time Javascript will not be looking in the queues of intervals and timeouts. When it finishes the program task (or is waiting for network interaction etc), it will start looking at that.
Calling a function inside of a variable declaration will execute the function and assign its return value to the variable.
Assigning a function to a variable, without calling, stores the function object inside of it. The variable can then be called to execute the function.
In this case, the first is true:
const myVar = setTimeout(func, 1000)
Because setTimeout is called inside the declaration, it executes. Its return value, which consists in a timer id, gets assigned to the variable.
I have a javascript function function a() that I want to be executed every 10 seconds.
I found that I can use the setInterval so that I can do something like: setInverval(a, 10000);
My question is the following:
Does this mean that
i) every 10 seconds the specified function is called (regardless if the previous execution is running/multithreaded way) OR
ii) that the function is called and when this function has finished execution then the next call of the function is scheduled after 10 seconds?
I am basically interested in option 2. If option 1 is what is happening by default then how could I achieve option 2?
Basically, setInterval runs according to option 1, except that if the function takes more than the interval time, it will not be fired again until it has finished and reached the next tick. For example, if you have an interval of 1 second and your function takes 1.5 seconds, it will run on the 2 second tick.
If you want the behaviour of option 2 (run X seconds after function completion), call setTimeout at the completion of your function instead:
setTimeout(function a() {
// your own code
setTimeout(a, 1000);
}, 1000);
How this works is that it first waits 1 second, then calls the function passed to setTimeout. At the end of the function, the function itself (a is the name of the function) is passed to setTimeout, which then waits another second to call the function again. This continues until JavaScript execution is halted or the timeout is removed by using clearTimeout.
Note that even if you use setInterval, the function will never be run concurrently, due to JavaScript's single-threaded nature.
setInterval(a, 10000) schedules a function to be called every 10 seconds, regardless of the time it took its previous invocations to complete. If you want to schedule the next call for 10 seconds after the completion of the last call, you should call setTimeout(a, 10000) within the a function itself, right before it returns, instead of using setInterval.
I have a javascript function that runs every 3 seconds, is there any way to do nothing if a previous instance of the function is already running?
I assume you are running heavy function with setInterval and want to skip one tick if previous one has not completed.
Then, instead of
function yourfoo() {
// code
}
setInterval(yourfoo, 3000);
do:
function yourfoo() {
// code
setTimeout(yourfoo, 3000);
}
setTimeout(yourfoo, 3000);
This guarantees next call is not scheduled until previous one is completed.
you could define a boolean flag to indicate the running state of the function on a higher scope, and switch it on or off accordingly.
Yes.
This is done by default.
It's called JavaScript is single threaded.
Two functions can't run at the same time.
Your probably using setInterval which will internally buffer function calls until any currently running code is finished.
JavaScript is single threaded, meaning that only one block of JavaScript will get executed at a given time. So even when the timer fires the execution of the code will be queued until the next available moment. Important to know is that if you're using a setInterval only one interval "fire" will get queued and all others will be dropped until there are no more intervals of this type on the queue.
Here's a great explanation of how this works by jQuery's father John Resig: http://ejohn.org/blog/how-javascript-timers-work/
You could rewrite your code to use setTimeout, because that way you're guaranteed that the next executing of the code will only take place after waiting at least the stated number of milliseconds (can be more if execution is blocked). Using setInterval the blocking could result in a back-to-back execution of the code if the code takes a long time to finish.
So, do something like this to prevent the back-to-back execution:
var nrOfMillisecondsToWait = 200;
setTimeout(function() {
.. your code here
}, nrOfMillisecondsToWait);
Why when calling fadeIn() onLoad does the browser run through the loop immediately. In other words there is an issue with either the setInterval or the Opacityto().
function Opacityto(elem,v){
elem.style.opacity = v/100;
elem.style.MozOpacity = v/100;
elem.style.KhtmlOpacity = v/100;
elem.style.filter=" alpha(opacity ="+v+")";}
function fadeIn(){
elem=document.getElementById('nav');
for (i=0;i==100;i++){
setInterval(Opacityto(elem,i),100);}
}
I think someone will tell me this can be done easiest with jQuery but I'm interested in doing it with javascript.
Thanks!HelP!
You've got several problems with your fadeIn() function:
A. Your for loop condition is i==100, which is not true on the first iteration and thus the body of the for loop will never be executed (the i++ won't ever happen). Perhaps you meant i<=100 or i<100 (depending on whether you want the loop to run 101 or 100 times)?
B. Your setInterval code has a syntax error EDIT: since you've updated your question to remove the quotes - setInterval expects either a string or a function reference/expression. So you need to either pass it the name of a function without parentheses and parameters, or a function expression like the anonymous function expression you can see in my code down below. in the way you try to build the string you are passing it. You've got this:
"Opacityto("+elem,i+")"
but you need this:
"Opacityto(elem," + i + ")"
The latter produces a string that, depending on i, looks like "Opacityto(elem,0)", i.e., it produces a valid piece of JavaScript that will call the Opacityto() function.
C. You probably want setTimeout() rather than setInterval(), because setInterval() will run your Opacityto() function every 100ms forever, while setTimeout() will run Opacityto() exactly once after the 100ms delay. Given that you are calling it in a loop I'm sure you don't really want to call setInterval() 100 times to cause your function Opacityto() to be run 100 times every 100ms forever.
D. Even fixing all of the above, your basic structure will not do what you want. When you call setInterval() or setTimeout() it does not pause execution of the current block of code. So the entire for loop will run and create all of your intervals/timeouts at once, and then when the 100ms is up they'll all be triggered more or less at once. If your intention is to gradually change the opacity with each change happening every 100ms then you need the following code (or some variation thereon):
function fadeIn(i){
// if called with no i parameter value initialise i
if (typeof i === "undefined") {
i = -1;
}
if (++i <= 100) {
Opacityto(document.getElementById('nav'), i);
setTimeout(function() { fadeIn(i); }, 100);
}
}
// kick it off:
fadeIn();
What the above does is defines fadeIn() and then calls it passing no parameter. The function checks if i is undefined and if so sets it to -1 (which is what happens if you call it without passing a parameter). Then it increments i and checks if the result is less than or equal to 100 and if so calls Opacityto() passing a reference to the element and i. Then it uses setTimeout() to call itself in 100ms time, passing the current i through. Because the setTimeout() is inside the if test, once i gets big enough the function stops setting timeouts and the whole process ends.
There are several other ways you could implement this, but that's just the first that happened as I started typing...
My guess is that there is a nasty comma inside the setInterval, messing the argument list:
"Opacityto("+elem,i+")"
^^^
here
You could try quoting the comma
+ "," +
but eval is evil so don't do that. The good way is to pass a real callback function:
function make_opacity_setter(elem, i){
return function(){
OpacityTo(elem, i);
};
}
...
setTimeout( make_opacity_setter(elem, i), 1000);
Do note that the intermediate function-making-function is needed to avoid the nasty interaction between closures and for-loops.
BTW, when you do
setInterval(func(), 1000)
you call func once yourself and then pass its return value to setInterval. since setInterval receives a junk value instead of a callback it won't work as you want to.
...or more specifically, how are they able to create animations via javascript, which is synchronous, without holding up the next javascript statement.
It's just a curiosity. Are they using a chain of setTimeout()? If so, are they set early, each one with a slightly longer duration than the previous, and running parallel? Or are they being created through a recursive function call, therefore running in series?
Or is it something completely different?
There is an alternative to setTimeout() called setInterval() which will call the function you pass as argument at regular intervals. Calling setInterval will return a value which can be passed to clearInterval to stop the function from being called.
With jQuery 1.4.2 on lines 5534 - 5536:
if ( t() && jQuery.timers.push(t) && !timerId ) {
timerId = setInterval(jQuery.fx.tick, 13);
}
Notice the setInterval for jQuery's tick method that triggers a step in an animation.
Chained calls to setTimeout aren't really "recursive". If one setTimeout function, when called, sets up another timeout with itself as the handler, the original invocation will be long gone by the time the new timeout occurs.
Using setTimeout instead of setInterval is (to me) often more flexible because it lets the timed code adapt (and possibly cancel) itself. The general pattern is to set up a closure around the setTimout call so that the data needed by the timed process (the animation, if that's what you're doing) is available and isolated from the rest of the app. Then the timeout is launched on its initial run.
Inside the timeout handler, "arguments.callee" can be used for it to refer to itself and reset the timeout for subsequent "frames."