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.)
Related
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.
Let's say I do this:
var timer = setTimeout(function() {
console.log("will this happen?");
}, 5000);
And then after just less than 5 seconds, another callback (from a network event in NodeJS for example) fires and clears it:
clearTimeout(timer);
Is there any possibility that the callback from the setTimeout call is already in the queue to be executed at this point, and if so will the clearTimeout be in time to stop it?
To clarify, I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it, but the other callback is currently running so the message is added to the queue. It seems like one of those race condition type things that would be easy to not account for.
Even though Node is single thread, the race condition the question describes is possible.
It can happen because timers are triggered by native code (in lib_uv).
On top of that, Node groups timers with the same timeout value. As a result, if you schedule two timers with the same timeout within the same ms, they will be added to the event queue at once.
But rest assured node internally solves that for you. Quoting code from node 0.12.0:
timer.js > clearTimeout
exports.clearTimeout = function(timer) {
if (timer && (timer[kOnTimeout] || timer._onTimeout)) {
timer[kOnTimeout] = timer._onTimeout = null;
// ...
}
}
On clearing a timeout, Node internally removes the reference to the callback function. So even if the race condition happens, it can do no harm, because those timers will be skipped:
listOnTimeout
if (!first._onTimeout) continue;
Node.js executes in a single thread.
So there cannot be any race conditions and you can reliably cancel the timeout before it triggers.
See also a related discussion (in browsers).
I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it
Without having looked at Node.js internals, I don't think this is possible. Everything is single-threaded, so the interpreter cannot be "in the process" of doing anything while your code is running.
Your code has to return control before the timeout can be triggered. If you put an infinite loop in your code, the whole system hangs. This is all "cooperative multitasking".
This behavior is defined in the HTML Standard, the fired task starts with:
If the entry for handle in the list of active timers has been cleared, then abort these steps.
Therefore even if the task has been queued already, it'll be aborted.
Whether this applies to Node.js, however, is debatable, as the documentation just states:
The timer functions within Node.js implement a similar API as the timers API provided by Web Browsers but use a different internal implementation that is built around the Node.js Event Loop.
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.
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).
In my application I found some JavaScript code that is using setInterval with 0 milliseconds, like so:
self.setInterval("myFunction()",0);
Obviously, this does not seem like a good idea to me. Can anyone tell me what will be the behaviour of setInterval here? ("myFunction" makes an AJAX call to the server)
I am asking this because I am having an irregular behaviour in my application. 90% of the times, the application behaves correctly and exactly one call to the server is made. However sometimes, multiple calls are made to the server (until now, maximum is 48 calls) and I am almost certain it is the fault of this line of code.
Browser set a minimal value for the interval. Usualy 10ms, but it can depend on the browser. This means repeat this as fast as I'm possibly allowed. The W3C spec say 4ms : http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers
This is correct but probably reveal a design error.
EDIT: By the way, it is bad practice to pass a string to setTimeout/setInterval, pass a function instead as javascript has first class functions.
setInterval(myFunction, 0) calls myFunction continuously with minimum delay. It is almost like calling myFunction in a infinite loop. Except that here you can stop the loop using the clearInterval method.
To have it executed only once with minor delay, use setTimeOut instead:
window.setTimeout(myFunction, 10);
As you're using AJAX, you don't have to use any timers at all - just call the next AJAX request in the Callback (complete/success event) of the current AJAX request.
Post your current code and we might be able to guide you further.
I assume that in myFunction() there is a clearInterval.
Basically, you've set an interval that can happen as often as possible. If the browser executing JavaScript actually gets to the clearInterval part before the next iteration of the interval, then it will be fine. Otherwise, it will happen again and again.
Use setTimeout instead.
setInterval with '0' moves the code execution at the end of the current thread. The code is put to the side, all other code in the thread is executed, and when there is no code for execution, then the side code is executed.