暂停并恢复setInterval

时间:2014-07-13 16:32:16

标签: javascript

window.setInterval(function(){
  //do stuff
}, milisec);

有没有办法随意停止这个间隔,并从它持续的地方恢复它?比如说,代码每5秒运行一次。我在第二秒的中间停止它,当恢复时,我希望它运行剩余的3秒并且每隔5秒继续运行。试。

3 个答案:

答案 0 :(得分:26)

试试这个:

1-当您想要pause计时器时,计算剩余的毫秒并将其存储在某处,然后拨打clearInterval

2-当你想要resume计时器时,只需拨打setTimeout,将上一步中存储的剩余时间作为参数。

3-在setTimeout的回调中,您应该再次致电setInterval

更新:这是你想要的,javascript: pause setTimeout();的更改版本归功于@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;
    }

用法:

    var timer = new IntervalTimer(function () {
        alert("Done!");
    }, 5000);

    window.setTimeout(function () {
        timer.pause();
        window.setTimeout(function () {
            timer.resume();
        }, 5000);
    }, 2000);

答案 1 :(得分:4)

为了背负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;
  }
}

答案 2 :(得分:2)

你应该只需要带有go和stop的setTimeout - 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();
}    
相关问题