JavaScript: Self-adjusting Timers 8 April 2014

JavaScript: Self-adjusting Timers

Ilya Markov
Script programmer at iRidium mobile

JavaScript: Self-adjusting Timers

The image to the post is a painting by Salvador Dali “Time flows”. The choice is not a chance one and essentially metaphorical.


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.


Personally I came across an impossibility to create an accurate timer by standard means: setTimeout() и setInterval() a couple of months ago, when I was working at a small project. The latency came up to inacceptable 0.5 sec.

James Edwards, a freelance web developer, specializing in JavaScript application development, suggests solving the task of accurate timing this way. The first thing to do to keep the timer accurate is to work out exactly how inaccurate it is, and subtract that difference from the next iteration. So, the following code was written:


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