Accurate Timer

by DSCallards

HTML

<div id="output"></div>

JavaScript

var $output = $('#output');

function display(text) {
    $output.append(text + '<br/>');
}

//call doTimer, passing in the number of milliseconds we want to time,
//and the interval. In this case we'll test every second for 20 minutes.
doTimer(1200000, 1000, function (e) {
    display(e)
}, function () {
    display('timer complete');
});

function doTimer(totalms, interval, oninstance, oncomplete) {
    //this function starts by initialising a time flag,
    //and noting the time the function was called
    var time = 0,
        start = new Date().getTime();

    //this sub-function increments the amount of time that is
    //expected to have passed by the interval (eg add 1 second)
    //we then calculate the actual elapsed time. 
    //When we reach the 20 minute limit the timer stops and calls the oncomplete method
    //if we haven't finished, 
    //we set another timeout for 1 second +/- the latency.
    function instance() {
        time += interval;
        elapsed = Math.floor(time / interval);
        if (time >= totalms) {
            oncomplete();
        } else {
            var diff = (new Date().getTime() - start) - time;
            window.setTimeout(instance, (interval - diff));
            oninstance(time + diff);
        }
    }
    //get the timer started!
    window.setTimeout(instance, interval);
}