【问题标题】:Why the interval will become faster and faster if I keep setting new interval如果我不断设置新的间隔,为什么间隔会越来越快
【发布时间】:2022-01-13 00:59:23
【问题描述】:

我正在用两个按钮做一个非常简单的计时器:stopset

代码如下:

   <h1>0</h1>
   <button onclick = 'set()'>Set</button>
   <button onclick = 'stop()'>Stop</button>

     var click = false;
        let interval
    function set(){
        interval = setInterval(function(){
    document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
        },1000)
    }
    function stop(){
        window.clearInterval(interval)
    }

我发现,如果我一直按set 按钮会设置新的间隔,h1 加 1 的速度会越来越快(比 1000 毫秒快得多)。

我知道我可以将两个按钮合并为一个按钮,或者将设置按钮变为display: none 或使用其他方式来防止这种情况。

但我只是想知道为什么会发生这种情况。

有人能解释一下为什么会发生这种情况吗?

感谢您的回复?

【问题讨论】:

  • 这真的很简单......你正在创建多个setInterval。这不是一次越来越快,而是在不同时间多次射击
  • 除非您明确单击停止按钮,否则您不会清理之前的间隔。您可以改为调用stop() 作为set() 逻辑的第一个操作。

标签: javascript setinterval


【解决方案1】:

那是因为您没有清除 set 函数上的前一个区间(只是重新分配它),所以如果您点击 set 三次,您将运行三个区间。

正确的代码应该是:

function set(){
  clearInterval(interval);

  interval = setInterval(function(){
    document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
  }, 1000)
}

【讨论】:

  • 我重新分配了之前的间隔。不是说interval的值会改变,间隔会自动关闭还是我必须用clearinterval来停止?
  • 您仍然必须使用 clearInterval
【解决方案2】:

另一种方式,更用户友好?

const h1_element = document.querySelector('h1')
    , btSet      = document.querySelector('#bt-set')
    , btStop     = document.querySelector('#bt-stop')
    ;
var interval = 0
  , counter  = 0
  ;
btSet.onclick =()=>
  {
  btSet.disabled = true
  btStop.disabled = false
  interval = setInterval( ()=> { h1_element.textContent = ++counter }, 1000 )
  }
btStop.onclick =()=>
  {
  clearInterval(interval)
  btSet.disabled  = false
  btStop.disabled = true
  }
<h1>0</h1>
<button id="bt-set">Set</button>
<button id="bt-stop" disabled>Stop</button>

【讨论】:

  • 感谢您为我提供了另一种有用的方法!
【解决方案3】:

另一种方式?更可靠,更优雅

利用 OOP:保证每个实例

运行一个唯一间隔

class IntervalManager {
   constructor(fn, delay){ this.fn= fn; this.delay= delay;}
   start() {this.stop(); this.id= setInterval(this.fn, this.delay);}
   stop() {if (this.id) clearInterval(this.id);}
}
//--- use it now

const counter = new IntervalManager(function(){
  let ui = document.querySelector('h1')
  ui.textContent = parseFloat(ui.textContent)+1
},1000);
<h1>0</h1>
<button onclick = 'counter.start()'>Set</button>
<button onclick = 'counter.stop()'>Stop</button>

以下其他示例显示了使用此管理器的好处:

class IntervalManager {
   constructor(fn, i){ this.fn= fn; this.i= i;}
   start() {this.stop(); this.id= setInterval(this.fn, this.i);}
   stop() {if (this.id) clearInterval(this.id);}
}
//--- use it now
//-- example 1
const timer = new IntervalManager(() => {
  document.querySelector('#timer h4').textContent = new Date()
}, 1000)

//-- example 2
counterIncrem= 0
const counter = new IntervalManager(() => {
  counterIncrem++;
  document.querySelector('#counter h4').textContent = counterIncrem
}, 1000)
<section id="timer">
  <h1>Timer</h1>
  <h4>_</h4>
  <button onclick = 'timer.start()'>Start</button>
  <button onclick = 'timer.stop()'>Stop</button>
</section>


<section id="counter">
  <h1>counter</h1>
  <h4>_</h4>
  <button onclick = 'counter.start()'>Start</button>
  <button onclick = 'counter.stop()'>Stop</button>
</section>

【讨论】:

  • 感谢您为我打开新的大门!我只是想知道interval manager 是什么?它是js中的库还是其他什么?你能告诉我一些关于它的细节吗,因为我试图在网上搜索,但找不到太多有用的信息。感谢您的帮助!
  • 这是一个概念!从技术上讲,我在那里添加了简单/小类 .. 没有更多 ? 我们是许多 JS 库的构建者。我们能够提供 3 行库 ? 如上所述(IntervalManager 类)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多