Reputation: 303
I got some problem with setInterval & clearInterval.
In my code, I set multiple intervals, and when count reduce to 0, stop the execution.
Like below:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" charset="utf-8">
</head>
<body>
<body>
<script type="text/javascript">
for (var i=0; i<4; i++){
var count = 100;
var IntervalID = window.setInterval((function(){ // closure
var timeoutID = IntervalID; // temp
var countTemp = count; // temp
var id = i;
return function(){
countTemp --;
console.log(id + " " + countTemp);
// do something here
if ( countTemp == 0 ){
clearInterval(timeoutID); // stop the execution
console.log(id + " stop");
}
}
})(), 20);
}
</script>
</body>
</html>
After the console appear the stop message "x stop", all element stop except the last element(id:3), it still going.
I try to write my code in another form:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" charset="utf-8">
</head>
<body>
<script type="text/javascript">
for (var i=0; i<4; i++){
doSomething(i);
}
function doSomething(id){
var count = 100;
var IntervalID = window.setInterval((function(){ // closure
var timeoutID = IntervalID; // temp
var countTemp = count; // temp
return function(){
countTemp --;
console.log(id + " " + countTemp);
// do something here
if ( countTemp == 0 ){
clearInterval(timeoutID); // stop the execution
console.log(id + " stop");
}
}
})(), 20);
}
</script>
</body>
</html>
But this time, all elements don't stop.
I have two questions:
1. What is difference between these two code?
2. How to make the code work fine?
Edit:
If you just want to make the code work, only change one line in the second snippet:
clearInterval(timeoutID); // stop the execution
to
clearInterval(IntervalID); // stop the execution
But other people's answer can solve what I confuse at this problem.
Upvotes: 0
Views: 1712
Reputation: 58
The problem is that the correct IntervalID is not being captured in your closure, by the time your closure runs, window.setInterval hasn't returned the id as the assignment expression has not finished yet.
A simple trick can be used with an object, since they are passed to functions by reference in JavaScript
I have modified the loop to accomplish this
for (var i=0; i < 4; i++){
var count = 100;
var args = { id: i, counter: count };
var IntervalID = window.setInterval((function(args){ // closure
return function(){
args.counter--;
console.log(args.id + " " + args.counter)
if ( args.counter == 0 ){
clearInterval(args.IntervalID); // stop the execution
console.log(args.id + " stop");
}
}.bind(args);
})(args), 20);
// by now the correct IntervalID will be captured
// as the assignment expression has finished executing
args.IntervalID = IntervalID;
}
Upvotes: 1