Will setInterval drift?
Here's a benchmark you can run in Firefox:
var start = +new Date();
var count = 0;
setInterval(function () {
console.log((new Date() - start) % 1000,
++count,
Math.round((new Date() - start)/1000))
}, 1000);
First value should be as close to 0 or 1000 as possible (any other value shows how "off the spot" the timing of the trigger was.) Second value is number of times the code has been triggered, and third value is how many times the could should have been triggered. You'll note that if you hog down your CPU it can get quite off the spot, but it seems to correct itself. Try to run it for a longer period of time and see how it handles.
setInterval timing slowly drifts away from staying accurate
I think I may have figured out a solution. I figured, if you can measure it you can compensate for it, right?
http://jsfiddle.net/zryNf/9/
var start;
var nextAt;
var f = function() {
if (!start) {
start = new Date().getTime();
nextAt = start;
}
nextAt += 1000;
var drift = (new Date().getTime() - start) % 1000;
$('<li>').text(drift + "ms").appendTo('#results');
setTimeout(f, nextAt - new Date().getTime());
};
f();
result varies a bit but here's a recent run:
0ms
7ms
2ms
1ms
1ms
1ms
2ms
1ms
1ms
1ms
So if it gets called 1ms, 2ms or even 10ms later than it should the next call is scheduled to compensate for that. As long as inaccuracy is only per call, but the clock should never lose time, then this should work well.
And now I wrapped this up a global accurateInterval
function which is a near drop in replacement for setInterval
. https://gist.github.com/1d99b3cd81d610ac7351
setInterval is not run at exact interval
While no Javascript running on a standard browser claims to be real-time (as pointed out in several comments) there are steps you an take to make things not get as out of hand as it appears the example in the question does (the errors being cumulative).
Just to start with an experiment I ran this on my Windows 10 Chrome:
const startTime = new Date().valueOf();
function printElapsedTime(startTime) {
let curTime = new Date().valueOf();
console.log(curTime - startTime);
}
let intervalObj = setInterval(printElapsedTime, 1000, startTime);
<div id="show">0</div>
setInterval will become unreliable and inaccurate sometimes
setTimeout and setInterval in javascript only promise that they won't be run before the specific time. they try to execute your function as soon as possible but they sometimes can't do that. They are not timers. They are some functions that call a callback after a time which is the minimum amount of waiting before calling the callback function. Unfortunately there is not an accurate timer in javascript. you can implement it yourself.
Edit: you may ask how:
read the following thread:
https://stackoverflow.com/a/29972322/12337783
Why setInterval runs slower than expected?
All scheduled code is put in a single queue and processed by one thread. If the setInterval
function can't finish faster than 10ms, the execution time will fall behind the schedule. The precise time of execution cannot be guaranteed.
How to compensate for setInterval timing drift in Javascript audio
Probably the best way to do this is to have a single, always active 1/8 note interval, then call the quarter-note every other tick:
// wrapped in a closure to allow for a private tickCount variable
// alternatively, you could use a more advanced object with start/stop methods, etc.
(function() {
var tickCount = 0,
tick = function() {
eighthNoteFunc();
if(tickCount %2 == 0) {
quarterNoteFunc();
}
tickCount++;
};
setInterval(tick, 300);
})();
This ensures that the methods are always called on the same tick. You can also expand this to support half notes (tickCount % 4 == 0
) and whole notes (tickCount % 8 == 0
).
This interested me, so I decided to create a fully-working sample (except, using animated backgrounds instead of audio): http://jsfiddle.net/SycBm/
This allows you to see the eighth-, quarter-, and half- notes ticking in sync, as well as start & stop the timer, and independently enable or disable the notes.
Enjoy!
Are there any disadvantages to using javascript setInerval with a long interval?
No, there is no disadvantage. However, the timer isn't the most accurate. See also: Will setInterval drift? This may not matter to you, as it is a bigger problem for timers fired rapidly. Plus, it doesn't soundl ike exact timing is a problem for you either.
Why are setTimeout and setInterval working differently in the browser and in Node.js?
This is because Chrome does self-correct the drift in setInterval
. node (and other browsers) don't. Note that currently specs agree with node, even if there is an active discussion to follow Chrome's behavior.
So in Chrome, it's like if you had a precise
at beginTime + 200
do fn
at beginTime + 400
do fn
at beginTime + 600
do fn
...etc
while in others it will be
at beginTime + 200
do fn
at now + 200
do fn
...etc.
But we know there will always be some delay preventing the timer to fire exactly when scheduled, and so in environments without drift correction, we end up with a now
that is later the expected time.
So in Chrome, the setInterval
job will be in the queue before the setTimeout
one, while in other environments, it will come after, because of the drift, even if infinitesimally small.
Related Topics
How to Get the Selected Radio Button Value Using Js
Losing "This" Context in JavaScript When Passing Around Members
How to Do Method Overloading in Typescript
Concerns, Decorators, Presenters, Service Objects, Helpers - Help Me Understand Them
Set Default Value of JavaScript Object Attributes
How Is a JavaScript String Not an Object
Rails - How to Include JavaScript Files Only on Certain Pages
How to Convert a String to Bytearray
How to Get Objects Value If Its Name Contains Dots
How to Serialize Dom Node to JSON Even If There Are Circular References
Access Elements of Parent Window from Iframe
How to Include HTML in a Js Rails Response
Inline Ruby in :JavaScript Haml Tag
R Networkd3 Package: Node Coloring in Simplenetwork()
Websocket Handshake with Ruby and Em::Websocket::Server
How to Use Source: Function()... and Ajax in Jquery UI Autocomplete