I have two questions related to the JavaScript's setInterval() method.
I haven't found any practical cases (but I guess it's not impossible also) related to these question, but for curiosity I wanted to ask these questions.
1.) What happens if the code to be be executed by the setInterval() takes more time than the time interval provided? Does the previous execution stops and the current one starts executing or both will run in parallel.
2.) What if the whole system (OS) is hanged between the time gap when setInterval() is called? Is it possible that the code can execute with some different interval during this condition? I mean does setInterval() guarantees that the code will be executed at the specified interval only?
Thanks
JavaScript uses single threaded execution. Functions such as setTimeout and setInterval lead many to believe that it is possible to multi-thread in JavaScript. In reality, setInterval and setTimeout merely schedule a function or expression to execute at a specified time and those functions are added to the same single-threaded stack. If the browser is in the middle of processing something else when a setTimeout or setInterval is scheduled to fire, the scheduled functions will execute as soon as the browser can get to it.
setInterval does not guarantee that a function will execute at the specified interval only. setInterval will try to execute a function at the specified time, but any number of things could delay the execution or prevent it from executing altogether.
Quoting this article by John Resing:
If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be longer than the desired delay).
Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified delay).
Related
This question already has answers here:
Is this recursion or not
(4 answers)
Why the function called by setTimeout has no callstack limit?
(2 answers)
Closed 2 years ago.
Given the following psudo-code (which is taken from my remote camera robot project)
[event handler](when event happens) {
[do some startup and init code]
start_everything_going();
}
// This block does something that will interact with the browser every 1/60 second.
def do_something() {
[code that does something goes here]
requestAnimationFrame(do_something);
}
def start_everything_going() {
requestAnimationFrame(do_something);
}
The way this works using requestAnimationFrame is that the event handler triggers, (say when a joystick is attached or activated), and after some setup or configuration code is run, it calls the initial function to begin the cyclical animation - start_everything_going().
Since requestAnimationFrame runs once and once only when called, it has to be repeatedly called to create a continuous effect.
The canonical method - and the one used in every example I have seen - is that the first invocation is done by a wrapper function called (eventually) by the event handler that triggers it, or something the event handler launches.
In order to repeatedly call requestAnimationFrame, the actual animating function calls requestAnimationFrame, with itself as the argument, as the last thing before exiting.
As far as I know, this is recursion, and is called recursion in all the docs about requestAnimationFrame I've seen. (i.e. MDN, Stack Overflow, (etc.).)
As I remember, a recursive call to a function creates yet another instance of the function, (leaving the original instance suspended in time somewhere), repeating the steps needed to do something. And this continues forever, creating additional instances of itself until, (eventually), some ending condition is reached.
Since, in this case, the called function never returns, there is no way to “unwind” the recursion. And, as far as I know, this will continue until either Hell freezes solid or all available computer resources have been exhausted.
Since this animation refreshes itself every 1/60th second, and can (theoretically) run for hours and hours and hours and hours and hours, what keeps this from folding up like a house of cards and crashing the system due to resource exhaustion?
It's not actually a recursive call in the function-stack sense, only in the broad sense.
When you call requestAnimationFrame(callbackFunction), the requestAnimationFrame function schedules the callback function with the browser to be called on the browser's next frame. Then requestAnimationFrame returns and gets popped off the stack, the function stack finishes executing until every other function returns and gets popped off the stack, and control is handed back to the browser.
In other words, the stack resolves fully, then on the next frame, the browser spins up the function stack again by executing callbackFunction.
A function calling itself is classic recursion, which is very common in programming when a complex algorithm needs to repeat itself, (like calculating a mathematical series or many digits of an irrational number like π).
There's an important distinction here. requestAnimationFrame doesn't actually call itself directly. callbackFunction calls requestAnimatonFrame, which then flags the browser to call callbackFunction on the next frame. Then requestAnimationFrame returns, and the function stack continues to resolve completely.
Since, in this case, the called function never returns, there is no way to “unwind” the recursion.
Technically the called function returns every frame, then the browser executes it again the next frame.
I've read this article:
http://ejohn.org/blog/how-javascript-timers-work/
and I understand that setInterval might drop some callback execution if the page is too busy.
I don't see how this would apply to setTimeout too, so is it safe to assume that setTimeout will always be executed (possibly some delay), or is it a case where a the setTimeout is dropped because of a busy process?
Yes. A function passed to setTimeout will execute at some point. While its timing is not guaranteed.
Yes - the "too busy" issue w/ set interval is touched upon somewhat in the last section about setInterval on the MDN. Set timeout, however, will always execute after some delay (it may not be the exact delay, ie your set timeout could be 5ms, but if the call stack is still full after the 5ms delay, then the callback wont be executed until the call stack is emptied.)
Since there is this function window.performance.now() that returns the current time in microseconds since the page started to load, is there a way to implement it's accuracy in to a more precise setTimeout function
The short answer is no, there isn't. In addition, the millisecond granularity of setTimeout is misleading. Some browsers are far less accurate, although there are workarounds for this. In any case, setTimeout calls are only called after the current call stack finishes executing, which could be much longer than you want. setInterval actually has an interesting behavior where it will queue up multiple calls if they're deferred by other executing code, so that when they execute they'll all execute one after another with no delay in between.
Short answer:no.
Long answer: Javascript doesn't guarantee an exact time-out period, just a minimum time-out period. Both setTimeout() and setInterval() defer the code and execute it when the thread becomes available. Measuring this to microseconds would be pointless.
I have a web site and i am using a javscript timer to swap images about.
I am using the timer like this:
var myTimer = window.setTimeout(MyFunction, MyInterval);
function MyFunction
{
//do something
//recalll timer
}
Now, the problem I have is not that the interval does not fire off at regular intervals as I can accept that in my application and I understand why it can vary.
The issue I have is that every now and then the timer stops for a few seconds and then resumes.
What I am trying ascertain is what is the main cause of this random suspension of the timer?
Is it due to the resources being diverted to another process on the hosting browser PC OR is it just the nature of using a JavaScript timer?
If the latter should I look to do an eternal loop? Everywhere I read and have practised elsewhere indicates that an infinite loop will grab all the resources and it would be a greater evil than the timer random suspension.
Are there any alternatives to using a javascript timer when a regular quick execution of code is paramount?
Thanks
The code you run inside MyFunction takes some time to execute (depending on what you are doing). When you recall the timer at the end of that function, the interval is not exactly MyInterval, because of the code execution time being added.
If you use setInterval() instead of setTimeout(), the given function will be executed exactly every MyInterval milliseconds rather than (MyInterval + execution time) milliseconds.
To answer your question, the random suspension happens because of the execution time of your code.
I had a similar issue on a website I was working on and ultimately found the culprit in another timer-triggered job in a jQuery plugin that was occasionally delaying execution of my own function. If you're using external code in your site, you could do some debugging to see if this is your case too.
As a possible remedy, you could give a look at web workers. Since worker tasks are executed in a separated thread, they are not subject to delay when something in your main thread is taking too long to complete.
Your code would then look like this:
var worker = new Worker('worker.js');
And in another file called "worker.js" you would write:
var myTimer = setTimeout(MyFunction, MyInterval);
function MyFunction
{
//do something
//recalll timer
}
Just note that there is no window. anymore before setTimeout. This is because web workers don't have direct access to the DOM.
It's not guaranteed to solve your problem, but it's worth a test.
When running in a browser, will setTimeout ever fire its code before the main program is done executing? Have the major browser vendors agreed on this behavior, or is it a side-effect of implementation? (or have they agreed to keep this side-effect in as standard behavior)
Consider a very simple (and useless) program.
setTimeout(function(){
console.log("Timeout Called")
},1);
for(var i=0;i<10000000;i++){};
console.log("done");
First we set a single micro-second setTimeout callback function which outputs Timeout Called to the console.
Then we spin in a loop for more than a micro-second.
Then we output done to the console.
When I run this program, it always outputs
done
Timeout Called
That is, the setTimeout callback functions aren't considered until the main program has run.
Is this reliable, defined behavior? Or are there times where the main program execution will be halted, the callback run, and then main program execution continued.
Yes, it is defined behaviour. It is a common misconception that Ajax callbacks undeterministically execute at some time, possibly before the current execution path finishes, when in reality they will always execute some time afterwards.
Javascript is single threaded and will never return to the event loop until the current thread finishes executing completely.
An asynchronous function, such as an event handler (includes Ajax) or a function that is scheduled with setInterval/setTimeout will never execute before the current execution path completes.
This is very well defined behavior.
The browser is not async and still has to wait for a previous action to complete before it does the next action
When using timeOut, it will wait first for the number of milliseconds that you passed, and then it will continue to wait until there is an opening in the code. Generally, this means it will wait until the code is done. The only exception (sort of) is when using other timeOuts or setIntervals. For example, if your loop had been
for(var i=0;i<10000000;i++){
setTimeout(function () {
console.log('One iteration');
}, 15);
};
Your output would be
done
Timeout Called
One iteration
One iteration
And so on.