Reputation: 2742
Here's a simple html&javascript: When I click on the "start" button, the counter starts, the number displayed being incremented, then when I click on the "start" again, the counter resets and starts all over again. (This is just a practice with setTimeout
and I don't intend to use this as anything.) At first I forgot to stop mainloop and was running another mainloop every time the button is clicked, which resulted in accelerated counting after repeated clicks. I saw this question (javascript - How to stop a setTimeout loop?) and managed to make it work.
And then I changed the javascript slightly. I thought these codes are almost equivalent, but it wasn't --- it no longer worked, multiple mainLoop seemed to be running after clicks. My question: why are these not equivalent? Why isn't the latter working?
Working codes:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div>
<pre id="start" style="background-color:green; width:70px; text-align:center;">Start</pre>
<pre id="count"></pre>
</div>
<script src="main.js"></script>
</body>
</html>
main.js
var counter = 0;
var timer;
function mainLoop(){
counter++;
document.getElementById("count").innerHTML=counter;
timer = setTimeout(mainLoop,100);
}
function start(){
if (timer){
// stop mainLoop that is currently running.
clearTimeout(timer);
}
// and start again.
counter = 0;
mainLoop();
}
document.getElementById("start").addEventListener("click",start);
Then I changed:
var counter = 0;
var timer;
function mainLoop(){
counter++;
document.getElementById("count").innerHTML=counter;
return setTimeout(mainLoop,100); // changed here
}
function start(){
if (timer){
clearTimeout(timer);
}
counter = 0;
timer = mainLoop(); // and here
}
document.getElementById("start").addEventListener("click",start);
Upvotes: 0
Views: 150
Reputation: 468
The reason you are getting multiple mainLoop
's is because in the mainLoop
, you are telling it to call itself every 100 milliseconds. Then it's returning setTimeout
to itself, instead of returning it to the start
method.
So you end up calling setTimeout more than once, but you arent storing the return value, which you need to pass to clearTimeout to cancel the loop.
What you could do is have something like the following:
function mainLoop() {
counter++;
document.getElementById("count").innerHTML=counter;
}
function start() {
if (timer){
clearTimeout(timer);
timer = undefined;
counter = 0;
} else {
timer = setInterval(mainLoop(), 100); // Set interval calls it every 100 milliseconds until it is cancelled
}
document.getElementById("start").addEventListener("click", start, false);
Upvotes: 1
Reputation: 2413
You execute clearTimeout(timer) before you set timer = mainLoop();
also i believe timer = mainloop() just runs the mainLoop function again timer is only the timeout function..
it look's like you're using setTimeout as an interval maybe you should look at this..
Upvotes: 1
Reputation: 7501
Your code will work the first time mainLoop
is called as the value is returned. The second time it is called it is called from setTimeout
, which means that the returned value (the value of the new timeout) is lost.
When you try to clear the timeout, you're trying to clear it using the value obtained from the very first call, which is a timeout which is passed in any case, not the current timeout value.
Try setting timer
in your mainLoop
.
Upvotes: 1
Reputation: 515
mainLoop is Looping itself, without setting the timer that's why.
Every-time the setTimeout get a new value , while you are stopping a old Timer if you don't update it.
You may wanna look into setInterval() instead thou, don't need repeatedly create Timer.
Upvotes: 2