Ilya Markov
Script programmer at iRidium mobile
In JS programming time may flow in a way, different from what we suppose it to. JavaScript is single-threaded. So, functions take turns for a piece of CPU time, and the time they have to wait varies, depending on the load. This is what causes latency in timers that can be up to 2-3msec. And this latency tends to accumulate. It’s crucially important, when controlling transient processes.
var start = new Date().getTime(),
time = 0,
elapsed = '0.0';
function instance()
{
time += 100;
elapsed = Math.floor(time / 100) / 10;
if(Math.round(elapsed) == elapsed) { elapsed += '.0'; }
var diff = (new Date().getTime() - start) - time;
IR.SetTimeout((100 - diff), instance);
}
IR.SetTimeout(100, instance,);
It’s a simple and good solution. The advantage is that it does not matter how inaccurate the timer is, as consequently the small latency of 3-4ms can be easily compensated. Whereas inaccuracy of a regular timer accumulates with each iteration and becomes noticeable.
As I mentioned I came across a problem of inaccurate times when working at a small audio project. After going into theory of creating accurate times in JS, I wrote the following code on the basis of the one suggested by James Edwards.
//when pressing "play/stop", a timer function is activated
function preciousTimer (step) {
//like in examples above, we take DateStamp for evaluation
var start = new Date().getTime(),
time = 0,
/*this variable was caused by the necessity
to have an even number as many iterations
as steps in the sequencer (the accuracy is still low)*/
it = 0;
function instance () {
//calculate the ideal time
time += step;
//calculate the difference
var diff = (new Date().getTime()- start) - time;
//act by the iterator value
if (it == 4) {
it = 0;
/*a place of sequencer working with matrix,
here we see the value of logic arrays
for every passage. */
if (m == 8) {
m = 0;
};
for (var i = 0; i < 4; i++) {
if (noteArr[i][m]) {
sound[i].play();
};
};
m++;
};
it++;
//if “pause” is pressed during an iteration,
//leave the end of the recursive chain
if (pause) {
return;
};
//call the next iteration, considering the latency
IR.SetTimeout((step - diff), instance);
};
//It’s the first call of instance function(),
//that starts the consequent call of iterations
setTimeout(step, instance);
};
The code written by me allows to play music continually, without time-lags. And it’s only one of the variants of using the code, written by James Edwards. Using it as a basis you can write your own self-adjusting timer for any purpose you want.
You can read the original of the article, used as a starting point of this post, here: Сreating accurate timers in JavaScript