为什么一直设置新的间隔时间间隔会越来越快
Why the interval will become faster and faster if I keep setting new interval
我正在用两个按钮做一个非常简单的计时器:stop
和 set
。
代码如下:
<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的速度会越来越快(比1000ms快很多) .
我知道我可以把两个按钮合为一个按钮,或者让设置的按钮变成display: none
或者用其他方法来防止这种情况。
但我只是想知道为什么会这样。
有人可以向我解释一下为什么会这样吗?
感谢任何回复?
那是因为你没有在你的 set
函数上清除之前的间隔(只是重新分配),所以如果你点击 set
三次,你就是 运行 三个间隔.
正确的代码应该是:
function set(){
clearInterval(interval);
interval = setInterval(function(){
document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
}, 1000)
}
另一种方式,对用户更友好?
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>
另一种方式?更多可靠,更多优雅
利用 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>
我正在用两个按钮做一个非常简单的计时器:stop
和 set
。
代码如下:
<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的速度会越来越快(比1000ms快很多) .
我知道我可以把两个按钮合为一个按钮,或者让设置的按钮变成display: none
或者用其他方法来防止这种情况。
但我只是想知道为什么会这样。
有人可以向我解释一下为什么会这样吗?
感谢任何回复?
那是因为你没有在你的 set
函数上清除之前的间隔(只是重新分配),所以如果你点击 set
三次,你就是 运行 三个间隔.
正确的代码应该是:
function set(){
clearInterval(interval);
interval = setInterval(function(){
document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
}, 1000)
}
另一种方式,对用户更友好?
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>
另一种方式?更多可靠,更多优雅
利用 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>