Skip to content

Instantly share code, notes, and snippets.

@manast
Last active November 15, 2023 22:08
Show Gist options
  • Star 62 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
  • Save manast/1185904 to your computer and use it in GitHub Desktop.
Save manast/1185904 to your computer and use it in GitHub Desktop.
Accurate Javascript setInterval replacement
function interval(duration, fn){
var _this = this
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
}
_this.timer = setTimeout(function(){
_this.run(end)
}, nextTick)
}
this.stop = function(){
clearTimeout(_this.timer)
}
}
@dehaotu
Copy link

dehaotu commented Oct 24, 2020

I am trying to implement this but it does not stop when this.interval.stop() is called, is there any reason why this could be? I am creating it with: that = this;
this.interval = new interval(that.state.timerint, function(){
that.noMetCount()
})

function interval(duration, fn){
  var _this = this
  _this.baseline = undefined
  
  _this.run = function(){
    if(_this.baseline === undefined){
      _this.baseline = new Date().getTime()
    }
    fn()
    _this.end = new Date().getTime()
    _this.baseline += duration
 
    _this.nextTick = duration - (_this.end - _this.baseline)
    if(_this.nextTick<0){
      _this.nextTick = 0
    }

    if (_this.run !== undefined) {
      _this.timer = setTimeout(function(){
        _this.run()
      }, _this.nextTick)
    }
  }

  _this.stop = function(){
    clearTimeout(_this.timer);
    _this.run = undefined;
  }

This works for me. What I assume has happened was, you were trying to call this.interval.stop() inside fn(), but in this case _this.run() will keep executing and creating a new setTimeout and assigned to _this.timer. To counter this, I marked _this.run as undefined in _this.stop, and before the assignment for _this.timer in the _this.run, I check if _this.run is still defined.

I hope this works for other people as well... Please correct me if I'm wrong.

@ihewro
Copy link

ihewro commented Apr 17, 2021

In the first time,it wait double douration, there is the fixed version and with the args:

export function Interval(fn,duration,...args){
    const _this = this;
    this.baseline = undefined

    this.run = function(flag){
        if(_this.baseline === undefined){
            _this.baseline = new Date().getTime() - duration
        }
        if (flag){
            fn(...args);
        }
        const end = new Date().getTime();
        _this.baseline += duration

        let nextTick = duration - (end - _this.baseline);
        if(nextTick<0){
            nextTick = 0
        }

        console.log(nextTick);
        _this.timer = setTimeout(function(){
            _this.run(true)
        }, nextTick)
    }

    this.stop = function(){
        clearTimeout(_this.timer)
    }
}

@docjojo
Copy link

docjojo commented Nov 15, 2023

Great tool!
Might want to have a look at https://github.com/docjojo/Timers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment