Пауза и возобновление setInterval
window.setInterval(function(){
//do stuff
}, milisec);
Есть ли способ остановить этот интервал по своему желанию и возобновить его с того места, где он длился? Скажем, код запускается каждые 5 секунд. Я останавливаю его в середине второй секунды, когда возобновляется, я хочу, чтобы он запустил оставшиеся 3 секунды и продолжал работать через каждые 5 сек. еще раз.
Ответы
Ответ 1
Попробуйте следующее:
1-, когда вы хотите pause
таймер, вычислить оставшиеся миллисекунды и сохранить его где-нибудь, затем вызвать clearInterval
.
2- Когда вы хотите resume
таймер, просто сделайте вызов setTimeout
, передав оставшееся время, сохраненное на предыдущем шаге, в качестве аргумента.
3- И в обратном вызове setTimeout
вы должны снова позвонить setInterval
.
UPDATE: это то, что вы хотите, измененная версия javascript: pause setTimeout(); благодаря @Felix Kling
function InvervalTimer(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;
}
Использование:
var timer = new InvervalTimer(function () {
alert("Done!");
}, 5000);
window.setTimeout(function () { timer.pause(); window.setTimeout(function () { timer.resume(); }, 5000); }, 2000);
Ответ 2
Вам нужно только setTimeout с go и stop - http://jsfiddle.net/devitate/QjdUR/1/
var cnt = 0;
var fivecnt = 0;
var go = false;
function timer() {
if(!go)
return;
cnt++;
if(cnt >= 5){
cnt=0;
everyFive();
}
jQuery("#counter").text(cnt);
setTimeout(timer, 1000);
}
function everyFive(){
fivecnt++;
jQuery("#fiver").text(fivecnt);
}
function stopTimer(){
go = false;
}
function startTimer(){
go = true;
timer();
}
Ответ 3
Чтобы ответить на вопрос Alireza, вот класс ES6, который делает то же самое с немного большей функциональностью и не запускается сразу. Вы можете установить максимальное количество раз, когда таймер погаснет, прежде чем автоматически останавливаться, и приостанавливать и возобновлять любое количество раз до того, как в следующий раз он отключится.
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;
}
}