暂停并恢复setInterval

Geo*_*iuc 19 javascript

window.setInterval(function(){
  //do stuff
}, milisec);
Run Code Online (Sandbox Code Playgroud)

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

Ali*_*eza 27

试试这个:

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;
    }
Run Code Online (Sandbox Code Playgroud)

用法:

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

    window.setTimeout(function () {
        timer.pause();
        window.setTimeout(function () {
            timer.resume();
        }, 5000);
    }, 2000);
Run Code Online (Sandbox Code Playgroud)


DSh*_*ook 6

为了支持 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;
  }
}
Run Code Online (Sandbox Code Playgroud)