[javascript] 자바 스크립트 : pause setTimeout ();

를 통해 설정된 활성 시간 제한이 실행중인 var t = setTimeout("dosomething()", 5000)경우

일시 중지하고 다시 시작할 수 있습니까?


현재 시간 초과에 남은 시간을 얻을 수있는 방법이 있습니까?
아니면 변수에 시간 제한이 설정되면 현재 시간을 저장하고 일시 중지하고 지금과 다음의 차이를 얻어야합니까?



답변

다음 window.setTimeout과 같이 포장 할 수 있습니다. 질문에서 제안한 내용과 비슷합니다.

var Timer = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        window.clearTimeout(timerId);
        timerId = window.setTimeout(callback, remaining);
    };

    this.resume();
};

var timer = new Timer(function() {
    alert("Done!");
}, 1000);

timer.pause();
// Do some stuff...
timer.resume();


답변

이와 같은 것이 트릭을 수행해야합니다.

function Timer(fn, countdown) {
    var ident, complete = false;

    function _time_diff(date1, date2) {
        return date2 ? date2 - date1 : new Date().getTime() - date1;
    }

    function cancel() {
        clearTimeout(ident);
    }

    function pause() {
        clearTimeout(ident);
        total_time_run = _time_diff(start_time);
        complete = total_time_run >= countdown;
    }

    function resume() {
        ident = complete ? -1 : setTimeout(fn, countdown - total_time_run);
    }

    var start_time = new Date().getTime();
    ident = setTimeout(fn, countdown);

    return { cancel: cancel, pause: pause, resume: resume };
}


답변

아니요. 취소 ( clearTimeout)하고 시작한 이후 시간을 측정 한 다음 새 시간으로 다시 시작해야합니다.


답변

Tim Downs 답변 의 약간 수정 된 버전입니다 . 그러나 Tim이 내 편집을 롤백 했기 때문에이 문제에 직접 답해야합니다. 내 솔루션을 사용하면 extra arguments를 세 번째 (3, 4, 5 …) 매개 변수로 사용하고 타이머를 지울 수 있습니다.

function Timer(callback, delay) {
    var args = arguments,
        self = this,
        timer, start;

    this.clear = function () {
        clearTimeout(timer);
    };

    this.pause = function () {
        this.clear();
        delay -= new Date() - start;
    };

    this.resume = function () {
        start = new Date();
        timer = setTimeout(function () {
            callback.apply(self, Array.prototype.slice.call(args, 2, args.length));
        }, delay);
    };

    this.resume();
}

Tim이 언급했듯이 추가 매개 변수는에서 사용할 수 IE lt 9없지만 에서 작동하도록 약간 작업했습니다 oldIE.

용법: new Timer(Function, Number, arg1, arg2, arg3...)

function callback(foo, bar) {
    console.log(foo); // "foo"
    console.log(bar); // "bar"
}

var timer = new Timer(callback, 1000, "foo", "bar");

timer.pause();
document.onclick = timer.resume;


답변

“일시 중지”와 “이력서”정말의 맥락에서 많은 이해가되지 않는 setTimeoutA는, 일회성 것. 의미 setInterval합니까? 그렇다면 일시 중지 할 수 없으며 취소 ( clearInterval) 만 한 다음 다시 예약 할 수 있습니다. 자세한 내용은 사양 의 타이머 섹션 에 있습니다.

// Setting
var t = setInterval(doSomething, 1000);

// Pausing (which is really stopping)
clearInterval(t);
t = 0;

// Resuming (which is really just setting again)
t = setInterval(doSomething, 1000);


답변

Timeout은 해결책을 찾기에 충분히 쉬웠지만 Interval은 약간 까다로 웠습니다.

이 문제를 해결하기 위해 다음 두 가지 클래스를 생각해 냈습니다.

function PauseableTimeout(func, delay){
    this.func = func;

    var _now = new Date().getTime();
    this.triggerTime = _now + delay;

    this.t = window.setTimeout(this.func,delay);

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();

        return this.triggerTime - now;
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();

        window.clearTimeout(this.t);
        this.t = null;
    }

    this.resume = function(){
        if (this.t == null){
            this.t = window.setTimeout(this.func, this.paused_timeLeft);
        }
    }

    this.clearTimeout = function(){ window.clearTimeout(this.t);}
}

function PauseableInterval(func, delay){
    this.func = func;
    this.delay = delay;

    this.triggerSetAt = new Date().getTime();
    this.triggerTime = this.triggerSetAt + this.delay;

    this.i = window.setInterval(this.func, this.delay);

    this.t_restart = null;

    this.paused_timeLeft = 0;

    this.getTimeLeft = function(){
        var now = new Date();
        return this.delay - ((now - this.triggerSetAt) % this.delay);
    }

    this.pause = function(){
        this.paused_timeLeft = this.getTimeLeft();
        window.clearInterval(this.i);
        this.i = null;
    }

    this.restart = function(sender){
        sender.i = window.setInterval(sender.func, sender.delay);
    }

    this.resume = function(){
        if (this.i == null){
            this.i = window.setTimeout(this.restart, this.paused_timeLeft, this);
        }
    }

    this.clearInterval = function(){ window.clearInterval(this.i);}
}

다음과 같이 구현할 수 있습니다.

var pt_hey = new PauseableTimeout(function(){
    alert("hello");
}, 2000);

window.setTimeout(function(){
    pt_hey.pause();
}, 1000);

window.setTimeout("pt_hey.start()", 2000);

이 예제는 2 초 후에 “hey”를 경고하도록 예약 된 일시 중지 가능한 제한 시간 (pt_hey)을 설정합니다. 다른 제한 시간은 1 초 후에 pt_hey를 일시 중지합니다. 세 번째 Timeout은 2 초 후에 pt_hey를 다시 시작합니다. pt_hey는 1 초 동안 실행되고 1 초 동안 일시 중지 된 다음 다시 실행됩니다. pt_hey는 3 초 후에 트리거됩니다.

이제 더 까다로운 간격

var pi_hey = new PauseableInterval(function(){
    console.log("hello world");
}, 2000);

window.setTimeout("pi_hey.pause()", 5000);

window.setTimeout("pi_hey.resume()", 6000);

이 예에서는 2 초마다 콘솔에 “hello world”를 작성하도록 일시 중지 가능한 간격 (pi_hey)을 설정합니다. 시간 초과는 5 초 후에 pi_hey를 일시 중지합니다. 또 다른 제한 시간은 6 초 후에 pi_hey를 재개합니다. 따라서 pi_hey는 두 번 트리거되고 1 초 동안 실행되고 1 초 동안 일시 중지되고 1 초 동안 실행 된 다음 2 초마다 트리거를 계속합니다.

기타 기능

  • clearTimeout ()clearInterval ()

    pt_hey.clearTimeout();pi_hey.clearInterval();시간 초과와 간격을 취소 할 수있는 쉬운 방법 역할을합니다.

  • getTimeLeft ()

    pt_hey.getTimeLeft();그리고 pi_hey.getTimeLeft();다음 트리거이 예약 될 때까지하는 시간을 밀리 초 단위로 반환합니다.


답변

진행률 표시 줄을 표시하려면 경과 및 남은 시간을 계산해야했습니다. 받아 들여진 대답을 사용하는 것은 쉽지 않았습니다. 이 작업에서는 ‘setInterval’이 ‘setTimeout’보다 낫습니다. 그래서 모든 프로젝트에서 사용할 수있는이 Timer 클래스를 만들었습니다.

https://jsfiddle.net/ashraffayad/t0mmv853/

'use strict';


    //Constructor
    var Timer = function(cb, delay) {
      this.cb = cb;
      this.delay = delay;
      this.elapsed = 0;
      this.remaining = this.delay - self.elapsed;
    };

    console.log(Timer);

    Timer.prototype = function() {
      var _start = function(x, y) {
          var self = this;
          if (self.elapsed < self.delay) {
            clearInterval(self.interval);
            self.interval = setInterval(function() {
              self.elapsed += 50;
              self.remaining = self.delay - self.elapsed;
              console.log('elapsed: ' + self.elapsed,
                          'remaining: ' + self.remaining,
                          'delay: ' + self.delay);
              if (self.elapsed >= self.delay) {
                clearInterval(self.interval);
                self.cb();
              }
            }, 50);
          }
        },
        _pause = function() {
          var self = this;
          clearInterval(self.interval);
        },
        _restart = function() {
          var self = this;
          self.elapsed = 0;
          console.log(self);
          clearInterval(self.interval);
          self.start();
        };

      //public member definitions
      return {
        start: _start,
        pause: _pause,
        restart: _restart
      };
    }();


    // - - - - - - - - how to use this class

    var restartBtn = document.getElementById('restart');
    var pauseBtn = document.getElementById('pause');
    var startBtn = document.getElementById('start');

    var timer = new Timer(function() {
      console.log('Done!');
    }, 2000);

    restartBtn.addEventListener('click', function(e) {
      timer.restart();
    });
    pauseBtn.addEventListener('click', function(e) {
      timer.pause();
    });
    startBtn.addEventListener('click', function(e) {
      timer.start();
    });