Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an elegant way to implement a clock-update event?

As far as I know (and I know relatively little), there is no native event that is emitted when e.g. the seconds hand ticks. The best I came up with is repeatedly checking a Date object (e.g. every 333ms; a shorter interval results in higher precision but is also more resource intensive). Somehow, if I use the same Date object over and over, time won't update, while

Date.prototype.getSeconds()

logs 'NaN' although typeof is 'number'.

    function clock(interval) {
    var d = new Date();
    var secondsOld = d.getSeconds();
    d = null;

    setInterval(function() {
        var d = new Date();
        var secondsNew = d.getSeconds();
        if ( secondsNew !== secondsOld ) {
            secondsOld = secondsNew;
            // trigger something
            console.log(secondsOld);
        }
        d = null;
    }, interval);
}
like image 937
suissidle Avatar asked May 27 '14 16:05

suissidle


1 Answers

You're right in that there are no native clock tick events. The most performant while precise way I would approach this issue is using setTimeout() and Date.now().

Create a recursive function that calls setTimeout() every second. To be precise, make the timeout the duration until the next exact second from that function call. Here's an example.

// milliseconds per second
var SECOND = 1000;

function bindClockTick(callback) {
    function tick() {
        var now = Date.now();

        callback(now);

        setTimeout(tick, SECOND - (now % SECOND));
    }

    tick();
}

bindClockTick(function(ms) {
    console.log('tick! milliseconds: '+ ms);
});

This uses Date.now() instead of creating a new instance of the Date class.

Here's a JSFiddle to test the precision. The demo uses new Date() to easily display the current time, but it can be done with just milliseconds.

like image 82
Austin Brunkhorst Avatar answered Nov 03 '22 00:11

Austin Brunkhorst