altandogan
altandogan

Reputation: 1285

setInterval(function(),time) change time on runtime

I want to change setInterval function time when my code is running.

I try this

<script type="text/javascript">
        $(function () {
            var timer;
            function come() { alert("here"); }
            timer = setInterval(come, 0);
            clearInterval(timer);
            timer = setInterval(come, 10000);
        });
    </script>

First SetInterval does not work!

Upvotes: 9

Views: 37864

Answers (7)

Elvin Chu
Elvin Chu

Reputation: 179

I know this is an old post, but I have implemented a typescript version for changing the interval in run time:

class LoopTimer {
  private timer: null | NodeJS.Timer;
  private callback: (...args: any[]) => void;
  private ms: number;
  private started: boolean;

  constructor(callback: (...args: any[]) => void, ms: number) {
    this.callback = callback;
    this.ms = ms;
    this.timer = null;
    this.started = false;
  }

  start() {
    if (!this.started) {
      this.timer = setInterval(this.callback, this.ms);
      this.started = true;
    }
  }

  stop() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
      this.started = false;
    }
  }

  get getStarted(): boolean {
    return this.started;
  }

  setInterval(ms: number) {
    this.ms = ms;
    if (this.started) {
      this.stop();
      this.start();
    }
  }
}

You can use it like this: The timer will stop and start again when interval is changed.

 const myTimer = new LoopTimer(()=>{
        console.log("Hello");
    }, 100);
    
myTimer.setInterval(500);

Upvotes: 4

DarckBlezzer
DarckBlezzer

Reputation: 4764

this is mi example, i think is more simple and easy to understand

const timer = {
  time: 5, // 5 time in seconds
  _time: null,
  _timeout: null,
  fun: () => {},
  start() {
    if (this._timeout == null) {
      const self = this;
      this.fun();
      this._timeout = setTimeout(function repeater() {
        self.fun();
        self._timeout = setTimeout(repeater, 1000 * self.time);
      }, 1000 * this.time);
    }
  },
  stop() {
    const timeout = this._timeout;
    this._timeout = null;
    this.set_time(); // set time to default
    clearTimeout(timeout);
  },
  set_time(time) {
    if (this._time == null) this._time = this.time;

    if (time) {
      this.time = time;
    } else {
      this.time = this._time;
    }
  },
};

Explication:

  • time: is the time of interval between every iteration, cycle or next call
  • _time: this variable save the default value of time, when use stop(), this variable(_time) restore "time"
  • start: this function start the iteration, if you call again, it will not duplicate.
  • stop: this function, stop the timeout and set default time and _timeout
  • set_time: this function set a new value to time, if you not send a parameter, time restore to default value, declare on running in this example is "5"

example:

const timer = {
      time: 5, // 5 time in seconds
      _time: null,
      _timeout: null,
      fun: () => {},
      start() {
        if (this._timeout == null) {
          const self = this;
          this.fun();
          this._timeout = setTimeout(function repeater() {
            self.fun();
            self._timeout = setTimeout(repeater, 1000 * self.time);
          }, 1000 * this.time);
        }
      },
      stop() {
        const timeout = this._timeout;
        this._timeout = null;
        this.set_time(); // set time to default
        clearTimeout(timeout);
      },
      set_time(time) {
        if (this._time == null) this._time = this.time;
    
        if (time) {
          this.time = time;
        } else {
          this.time = this._time;
        }
      },
    };
    
// print time
timer.fun = () =>{
    console.log(new Date())
};
timer.set_time(10)
timer.start()

Upvotes: 1

Jaapze
Jaapze

Reputation: 742

I know this post is old, but i needed something similar, maybe someone needs it.

This is a version without setInterval, based on the code from the other reaction (Niet the Dark Absol).

function timer()
{
    var timer = {
        running: false,
        iv: 5000,
        timeout: false,
        cb : function(){},
        start : function(cb,iv,sd){
            var elm = this;
            clearInterval(this.timeout);
            this.running = true;
            if(cb) this.cb = cb;
            if(iv) this.iv = iv;
            if(sd) elm.execute(elm);
            this.timeout = setTimeout(function(){elm.execute(elm)}, this.iv);
        },
        execute : function(e){
            if(!e.running) return false;
            e.cb();
            e.start();
        },
        stop : function(){
            this.running = false;
        },
        set_interval : function(iv){
            clearInterval(this.timeout);
            this.start(false, iv);
        }
    };
    return timer;
}

Usage:

var timer_1 = new timer();
timer_1.start(function(){
    //magic here
}, 2000, false);

var timer_2 = new timer();
timer_2.start(function(){
    //more magic here
}, 3000, true);

//change the interval
timer_2.set_interval(4000);

//stop the timer
timer_1.stop();

The last parameter of the start function is a boolean if the function needs to be run at 0.

You can also find the script here: https://github.com/Atticweb/smart-interval

Upvotes: 0

adeneo
adeneo

Reputation: 318252

You're clearing the interval on the next line, so the first one wont work, as it gets cleared right away :

        timer = setInterval(come, 0);
        clearInterval(timer);
        timer = setInterval(come, 10000);

Also, as gdoron says, setting a interval of nothing isn't really valid, and not a really good idea either, use setTimeout instead, or just run the function outright if no delay is needed.

        come();
        clearInterval(timer);
        timer = setInterval(come, 10000);

Upvotes: 15

Bergi
Bergi

Reputation: 664650

You can't. You will need to use setTimeout, and call it repetitively:

var timer; // current timeout id to clear
function come(){ /* do something */};
var time; // dynamic interval

(function repeat() {
    come();
    timer = setTimeout(repeat, time);
})();

With this you can set a different "interval" to be applied each time the function repeat is executed. Yet, nothing changes if alter time during a timeout, you'd need to stop the timeout for that.

Upvotes: 7

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324680

There is no way to directly change the interval at which a function fires. The best you can do is cancel an interval and set a new one with the same function and updated timer. Here's a possible way of doing it:

timer = {
    timers:{},
    inc:0,
    start:function(cb,gap) {
        var key = inc;
        inc++;
        timer.timers[key] = [setInterval(cb,gap),cb];
        return key;
    },
    stop:function(id) {
        if( !timer.timers[id]) return;
        clearInterval(timer.timers[id][0]);
        delete timer.timers[id];
    },
    change:function(id,newgap) {
        if( !timer.timers[id]) return;
        clearInterval(timer.timers[id][0]);
        setInterval(timer.timers[id][1],newgap);
    }
};

Usage:

var myTimer = timer.start(function() {....},1000);
// calls every second

timer.change(myTimer,5000);
// now calls every five seconds

Upvotes: 3

gdoron
gdoron

Reputation: 150263

timer = setInterval(come, 0); // zero isn't a valid interval...

You probably wants:

come();
timer = setInterval(come, 10000);

docs on MDN:

delay is the number of milliseconds (thousandths of a second) that the setInterval() function should wait before each call to func. As with setTimeout, there is a minimum delay enforced.

And:

Historically browsers implement setTimeout() "clamping": successive setTimeout() calls with delay smaller than the "minimum delay" limit are forced to the use at least the minimum delay. The minimum delay, DOM_MIN_TIMEOUT_VALUE, is 4 ms (stored in a preference in Firefox: dom.min_timeout_value), with a DOM_CLAMP_TIMEOUT_NESTING_LEVEL of 5ms.

Upvotes: 1

Related Questions