Create a gist now

Instantly share code, notes, and snippets.

Embed
Accurate Javascript setInterval replacement
function interval(duration, fn){
this.baseline = undefined
this.run = function(){
if(this.baseline === undefined){
this.baseline = new Date().getTime()
}
fn()
var end = new Date().getTime()
this.baseline += duration
var nextTick = duration - (end - this.baseline)
if(nextTick<0){
nextTick = 0
}
(function(i){
i.timer = setTimeout(function(){
i.run(end)
}, nextTick)
}(this))
}
this.stop = function(){
clearTimeout(this.timer)
}
}
@manast

This comment has been minimized.

Show comment
Hide comment
@manast

manast Sep 1, 2011

This code snippet can be used when a very accurate setInterval is needed. It will always be accurate ( 1+-ms in variance, but the mean will be the exact duration). Of course the function provided must run faster than the duration parameter. If for some reason the function takes more time than the duration in some occasions, the timer will still converge to the exact intervals very fast.

Example of use:

var timer = new interval(50, function(){
      console.log(new Date().getTime())
    })
    timer.run()
Owner

manast commented Sep 1, 2011

This code snippet can be used when a very accurate setInterval is needed. It will always be accurate ( 1+-ms in variance, but the mean will be the exact duration). Of course the function provided must run faster than the duration parameter. If for some reason the function takes more time than the duration in some occasions, the timer will still converge to the exact intervals very fast.

Example of use:

var timer = new interval(50, function(){
      console.log(new Date().getTime())
    })
    timer.run()
@sessa

This comment has been minimized.

Show comment
Hide comment
@sessa

sessa Jun 21, 2012

Did you snag this from another programming language?

sessa commented Jun 21, 2012

Did you snag this from another programming language?

@manast

This comment has been minimized.

Show comment
Hide comment
@manast

manast Jun 21, 2012

I did not, but this was written when I was quite new in javascript. I have a better version of this code in our framework: https://github.com/OptimalBits/ginger/blob/master/ginger.js

But of course it depends on other things, it is not lightweight as the one in the gist. In any case I am planing a new interval/timer that is a bit more powerful, I want to be able to keep just one timer for all the intervals instances.

Owner

manast commented Jun 21, 2012

I did not, but this was written when I was quite new in javascript. I have a better version of this code in our framework: https://github.com/OptimalBits/ginger/blob/master/ginger.js

But of course it depends on other things, it is not lightweight as the one in the gist. In any case I am planing a new interval/timer that is a bit more powerful, I want to be able to keep just one timer for all the intervals instances.

@ezabba

This comment has been minimized.

Show comment
Hide comment
@ezabba

ezabba Jul 26, 2012

on line 20 shouldn't be

})(this)

instead of

}(this))

?

ezabba commented Jul 26, 2012

on line 20 shouldn't be

})(this)

instead of

}(this))

?

@ArnaudRinquin

This comment has been minimized.

Show comment
Hide comment
@ArnaudRinquin

ArnaudRinquin Nov 28, 2012

You are tight ezabba

You are tight ezabba

@ArnaudRinquin

This comment has been minimized.

Show comment
Hide comment
@ArnaudRinquin

ArnaudRinquin Nov 28, 2012

right*

right*

@tanepiper

This comment has been minimized.

Show comment
Hide comment
@tanepiper

tanepiper Dec 5, 2012

@manast - I've implemented a new version of this at https://gist.github.com/4215634

Rather than calculate the difference between an updated baseline, this instead takes a start time and current time, and calculates a pretty accurate tick value to compensate for drift - I've had this running for hours and keep accurate to within 1-5ms.

A bonus of this version if you use the default 1000ms (1s) tick value, it also gives you an accurate H/M/S timing, as shown in the timer example

@manast - I've implemented a new version of this at https://gist.github.com/4215634

Rather than calculate the difference between an updated baseline, this instead takes a start time and current time, and calculates a pretty accurate tick value to compensate for drift - I've had this running for hours and keep accurate to within 1-5ms.

A bonus of this version if you use the default 1000ms (1s) tick value, it also gives you an accurate H/M/S timing, as shown in the timer example

@Germanaz0

This comment has been minimized.

Show comment
Hide comment
@Germanaz0

Germanaz0 May 28, 2015

This has a problem, when the window lose the focus, the timers speed up after focus again.

This has a problem, when the window lose the focus, the timers speed up after focus again.

@weednation12

This comment has been minimized.

Show comment
Hide comment
@weednation12

weednation12 Nov 5, 2015

Good code, integrated it and works perfect!

Good code, integrated it and works perfect!

@englishextra

This comment has been minimized.

Show comment
Hide comment
@englishextra

englishextra Jun 12, 2016

@manast
I would add

timer && timer.run();

Why? Consider the code below:

        var si = new interval(50, function () {
                if ("undefined" !== typeof hiddenPreloadImage && hiddenPreloadImage && 0 !== si) {
                    si.stop(),
                    si = 0;
                    setStyleOpacity(superbox, 1),
                    setImmediate(function () {
                        window.progressBar && (progressBar.finish(), progressBar.hide());
                    });
                }
            });
        si && si.run();

@manast
I would add

timer && timer.run();

Why? Consider the code below:

        var si = new interval(50, function () {
                if ("undefined" !== typeof hiddenPreloadImage && hiddenPreloadImage && 0 !== si) {
                    si.stop(),
                    si = 0;
                    setStyleOpacity(superbox, 1),
                    setImmediate(function () {
                        window.progressBar && (progressBar.finish(), progressBar.hide());
                    });
                }
            });
        si && si.run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment