如何暂停 setInterval() 函数?

IT技术 javascript setinterval
2021-01-19 06:29:48

如何使用 Javascript 暂停和恢复 setInterval() 函数?

例如,也许我有一个秒表来告诉你你浏览网页的秒数。有一个“暂停”和“继续”按钮。clearInterval() 在这里不起作用的原因是,如果用户在第 40 秒和第 800 毫秒单击“暂停”按钮,当他单击“继续”按钮时,经过的秒数必须增加 1 200 毫秒。如果我对计时器变量使用 clearInterval() 函数(单击暂停按钮时),然后再次对计时器变量使用 setInterval() 函数(单击恢复按钮时),经过的秒数将增加1 仅在 1000 毫秒后,这会破坏秒表的准确性。

那我该怎么做呢?

6个回答

您可以使用标志来跟踪状态:

var output = $('h1');
var isPaused = false;
var time = 0;
var t = window.setInterval(function() {
  if(!isPaused) {
    time++;
    output.text("Seconds: " + time);
  }
}, 1000);

//with jquery
$('.pause').on('click', function(e) {
  e.preventDefault();
  isPaused = true;
});

$('.play').on('click', function(e) {
  e.preventDefault();
  isPaused = false;
});
h1 {
    font-family: Helvetica, Verdana, sans-serif;
    font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Seconds: 0</h1>
<button class="play">Play</button>
<button class="pause">Pause</button>

这正是我会做的,我不确定您是否真的可以暂停 setInterval。

注意:这个系统很简单,对于不需要高精度的应用程序来说效果很好,但它不会考虑滴答之间经过的时间:如果你在半秒后点击暂停,然后点击播放你的时间将关闭半秒。

无论如何,我喜欢这个想法(简单而干净)并且我将它与我的代码一起使用,其中没有杀戮。 This comment is just to notify those who are going to kill some one with their script
2021-03-16 06:29:48
最终,out run by the time.如果您有多个clickwith.pause.play,您将无法预测将在哪个n/1000部分click制作。从而使 的损失n/1000 Sec或收益(1000-n)/1000 sec但在某些情况下,这是没有意义的,但在某些令人叹为观止的情况下,它们会造成很大的伤害。
2021-03-23 06:29:48
不错的把戏。感谢您的回答,但您没有暂停 setInterval 函数。
2021-03-25 06:29:48
你不能暂停 setInterval 函数,你可以停止它(clearInterval),或者让它运行。我提供的解决方案是针对 OP 问题的解决方案,我并没有声称它适用于所有可能的场景。
2021-03-31 06:29:48
那并没有解决他的问题。结果仍然是概率性的。更好的选择是清除间隔,并增加自上次点火以来经过的时间。间隔事件可能会将其增加 1,而暂停事件可能会将其增加 0.42。但是您还需要存储每个间隔触发的时间,以便您可以与之进行比较。Date.now() 就是你想要的函数。
2021-04-01 06:29:48

你不应该在区间函数中测量时间。相反,只需在计时器启动时节省时间并在计时器停止/暂停时测量差异。仅使用 setInterval 更新显示值。因此无需暂停计时器,您将通过这种方式获得尽可能高的准确性。

为什么有人不应该在一个间隔内测量时间?如果他们想显示实时计时器/倒计时,那么无论如何他们都需要每秒重新计算经过的持续时间,为什么不在那里跟踪呢?
2021-03-17 06:29:48

虽然@Jonas Giuro 说得对:

你不能暂停 setInterval 函数,你可以停止它(clearInterval),或者让它运行

另一方面,这种行为可以用@VitaliyG 建议的方法来模拟

你不应该在区间函数中测量时间。相反,只需在计时器启动时节省时间并在计时器停止/暂停时测量差异。仅使用 setInterval 更新显示值。

var output = $('h1');
var isPaused = false;
var time = new Date();
var offset = 0;
var t = window.setInterval(function() {
  if(!isPaused) {
    var milisec = offset + (new Date()).getTime() - time.getTime();
    output.text(parseInt(milisec / 1000) + "s " + (milisec % 1000));
  }
}, 10);

//with jquery
$('.toggle').on('click', function(e) {
  e.preventDefault();
  isPaused = !isPaused;
  if (isPaused) {
    offset += (new Date()).getTime() - time.getTime();
  } else {
    time = new Date();
  }

});
h1 {
    font-family: Helvetica, Verdana, sans-serif;
    font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Seconds: 0</h1>
<button class="toggle">Toggle</button>

为什么不使用更简单的方法呢?添加一个class!

只需添加一个类,告诉间隔不要做任何事情。例如:悬停时。

var i = 0;
this.setInterval(function() {
  if(!$('#counter').hasClass('pauseInterval')) { //only run if it hasn't got this class 'pauseInterval'
    console.log('Counting...');
    $('#counter').html(i++); //just for explaining and showing
  } else {
    console.log('Stopped counting');
  }
}, 500);

/* In this example, I'm adding a class on mouseover and remove it again on mouseleave. You can of course do pretty much whatever you like */
$('#counter').hover(function() { //mouse enter
    $(this).addClass('pauseInterval');
  },function() { //mouse leave
    $(this).removeClass('pauseInterval');
  }
);

/* Other example */
$('#pauseInterval').click(function() {
  $('#counter').toggleClass('pauseInterval');
});
body {
  background-color: #eee;
  font-family: Calibri, Arial, sans-serif;
}
#counter {
  width: 50%;
  background: #ddd;
  border: 2px solid #009afd;
  border-radius: 5px;
  padding: 5px;
  text-align: center;
  transition: .3s;
  margin: 0 auto;
}
#counter.pauseInterval {
  border-color: red;  
}
<!-- you'll need jQuery for this. If you really want a vanilla version, ask -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<p id="counter">&nbsp;</p>
<button id="pauseInterval">Pause</button></p>

多年来,我一直在寻找这种快速简便的方法,因此我发布了多个版本,以向尽可能多的人介绍它。

我的简单方法:

function Timer (callback, delay) {
  let callbackStartTime
  let remaining = 0

  this.timerId = null
  this.paused = false

  this.pause = () => {
    this.clear()
    remaining -= Date.now() - callbackStartTime
    this.paused = true
  }
  this.resume = () => {
    window.setTimeout(this.setTimeout.bind(this), remaining)
    this.paused = false
  }
  this.setTimeout = () => {
    this.clear()
    this.timerId = window.setInterval(() => {
      callbackStartTime = Date.now()
      callback()
    }, delay)
  }
  this.clear = () => {
    window.clearInterval(this.timerId)
  }

  this.setTimeout()
}

如何使用:

代码写得很快,没有重构,如果你想让我改进代码并给出 ES2015 版本(类),请提高我的答案的评分。