window.setInterval(function(){ //do stuff }, milisec);
Is there a way to stop this interval at will, and to resume it from where it lasted? Say, code runs every 5 sec. I stop it in the middle of the 2nd second, when resumed, I want it to run the remaining 3 seconds and continue to run afterwards every 5 sec. again.
You cannot PAUSE the setInterval function, you can either STOP it (clearInterval), or let it run.
To pause setInterval() functions with JavaScript, we call the clearInterval function. let doThis = null; const y = () => { //... }; doThis = setInterval(y, 1000); const yStart = () => { doThis = setInterval(y, 1000); }; const yStop = () => { clearInterval(doThis); };
setTimeout allows us to run a function once after the interval of time. setInterval allows us to run a function repeatedly, starting after the interval of time, then repeating continuously at that interval.
Try this:
1- when you want to pause
the timer, calculate the remaining milliseconds and store it somewhere then call clearInterval
.
2- When you want to resume
the timer, just make a call to setTimeout
passing the remaining time stored in the previous step as the argument.
3- And in setTimeout
's callback you should call setInterval
again.
UPDATE: This is what you want, a changed version of javascript: pause setTimeout(); thanks to @Felix Kling
function IntervalTimer(callback, interval) { var timerId, startTime, remaining = 0; var state = 0; // 0 = idle, 1 = running, 2 = paused, 3= resumed this.pause = function () { if (state != 1) return; remaining = interval - (new Date() - startTime); window.clearInterval(timerId); state = 2; }; this.resume = function () { if (state != 2) return; state = 3; window.setTimeout(this.timeoutCallback, remaining); }; this.timeoutCallback = function () { if (state != 3) return; callback(); startTime = new Date(); timerId = window.setInterval(callback, interval); state = 1; }; startTime = new Date(); timerId = window.setInterval(callback, interval); state = 1; }
Usage:
var timer = new IntervalTimer(function () { alert("Done!"); }, 5000); window.setTimeout(function () { timer.pause(); window.setTimeout(function () { timer.resume(); }, 5000); }, 2000);
To piggyback off Alireza's answer, here's an ES6 class that does the same thing with a bit more functionality, and doesn't start right away. You can set a maximum number of times the timer will fire off before automatically stopping, and pause and resume any number of times before the next time it's set to fire off.
export default class IntervalTimer{ constructor(name, callback, interval, maxFires = null){ this.remaining = 0; this.state = 0; // 0 = idle, 1 = running, 2 = paused, 3= resumed this.name = name; this.interval = interval; //in ms this.callback = callback; this.maxFires = maxFires; this.pausedTime = 0; //how long we've been paused for this.fires = 0; } proxyCallback(){ if(this.maxFires != null && this.fires >= this.maxFires){ this.stop(); return; } this.lastTimeFired = new Date(); this.fires++; this.callback(); } start(){ this.log.info('Starting Timer ' + this.name); this.timerId = setInterval(() => this.proxyCallback(), this.interval); this.lastTimeFired = new Date(); this.state = 1; this.fires = 0; } pause(){ if (this.state != 1 && this.state != 3) return; this.log.info('Pausing Timer ' + this.name); this.remaining = this.interval - (new Date() - this.lastTimeFired) + this.pausedTime; this.lastPauseTime = new Date(); clearInterval(this.timerId); clearTimeout(this.resumeId); this.state = 2; } resume(){ if (this.state != 2) return; this.pausedTime += new Date() - this.lastPauseTime; this.log.info(`Resuming Timer ${this.name} with ${this.remaining} remaining`); this.state = 3; this.resumeId = setTimeout(() => this.timeoutCallback(), this.remaining); } timeoutCallback(){ if (this.state != 3) return; this.pausedTime = 0; this.proxyCallback(); this.start(); } stop(){ if(this.state === 0) return; this.log.info('Stopping Timer %s. Fired %s/%s times', this.name, this.fires, this.maxFires); clearInterval(this.timerId); clearTimeout(this.resumeId); this.state = 0; } //set a new interval to use on the next interval loop setInterval(newInterval){ this.log.info('Changing interval from %s to %s for %s', this.interval, newInterval, this.name); //if we're running do a little switch-er-oo if(this.state == 1){ this.pause(); this.interval = newInterval; this.resume(); } //if we're already stopped, idle, or paused just switch it else{ this.interval = newInterval; } } setMaxFires(newMax){ if(newMax != null && this.fires >= newMax){ this.stop(); } this.maxFires = newMax; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With