Reputation: 7407
I have 2 setInterval function (okay guys, sorry, I thought the code inside may be redundant and will make the question become localized :/ but anyway, here it is:
$('#armStatus').click(function(){
armingloop = setInterval(function () {
if ($checkbox.is(':checked ')) {
$.post('/request', {
key_pressed: "arming_status"
}).done(function (reply) {
$arm.empty().append("<h3>The Arming Status is " + reply + "</h3>").show();
$arm.show();
});
} else {
$arm.hide();
}
}, 3000);
});
and
$('#monitor').click(function () {
bigloop = setInterval(function () {
var checked = $('#status_table tr [id^="monitor_"]:checked');
if (checked.index() === -1 || checked.length === 0) {
clearloop(bigloop);
$('#monitor').button('enable');
} else {
//$('#monitor').button('enable'); //enable the monitor button
(function loop(i) {
//monitor element at index i
monitoring($(checked[i]).parents('tr'));
//delay of 3 seconds
setTimeout(function () {
//when incremented i is less than the number of rows, call loop for next index
if (++i < checked.length) loop(i);
}, 3000);
}(0)); //start with 0
}
}, index * 3000); //loop period
});
function clearloop(loopname){
bigloop= window.clearInterval(loopname);
}
Both will be triggered by a different selector. I observe that when the bigloop
is activated, and armingloop
is also activated at a later time, the status update function monitoring
in my bigloop
is affected (e.g. status reply is captured by wrong element.)
Note that I have a setTimer
as well.
My question here is, how can i make sure any 2 setInterval
s are isolated and will not affect each other?
Upvotes: 2
Views: 2690
Reputation: 772
How are the intervals triggered?
Maybe you can try to call them in for example a click function:
$('<ELEMENT>').click( function() {
setInterval(function(){
},3000);
});
$('<ELEMENT>').click( function() {
setInterval(function () {
var checked = $('#status_table tr [id^="monitor_"]:checked');
if (checked.index()===-1 ||checked.length===0){
clearloop(bigloop);
$('#monitor').button('enable');
}else{
//$('#monitor').button('enable'); //enable the monitor button
(function loop(i) {
//monitor element at index i
monitoring($(checked[i]).parents('tr'));
//delay of 3 seconds
setTimeout(function () {
//when incremented i is less than the number of rows, call loop for next index
if (++i < checked.length) loop(i);
}, 3000);
}(0)); //start with 0
}
}, index*3000); //loop period
});
Upvotes: 0
Reputation: 38345
How can I make sure any 2 setIntervals are isolated and will not affect each other?
Variable scope
Make sure that all of the variables involved are correctly scoped, and avoid adding any to the global scope unless it's completely unavoidable (this shouldn't be the case). This means you'll want to be using the var
keyword whenever you declare any variables.
If your variables are correctly scoped to their respective setInterval
calls then there's no danger of one affecting values in the other, even if you've used the same variable names.
Check your logic
If you're querying, and then modifying, the same set of elements on the page in both of them then they can't be independent, since changes in one of them will then be reflected in the next execution of the other one. Any shared logic, any use of global variables, etc. are all potential candidates for issues to be introduced.
Essentially you're looking for any overlap between the two, and then (hopefully) eliminating that. If it can't be eliminated then your two setIntervals can't be isolated, and you either have to accept that the two are linked or find another approach to solving the problem.
Upvotes: 1
Reputation:
You simply can't as they have no guarantee of order. They are added to an event queue together with other events (incl. repaints etc.), and which ever comes first is called.
A better implementation would be in your main loop to throw a CustomEvent
which your monitor is listening to.
Simplified:
// global flag for monitoring
var isMonitoring = true,
armingloop;
// the function we use to update monitor.
// This will be called every time we send an event
function updateMonitor(e) {
/* ... update ... */
// ie. e.detail.mydata
}
// Start listening to 'monitor' event. If received, call
// the function above (only reference the function).
window.addEventListener('monitor', updateMonitor, false);
// The main loop. Self-triggering for loop by calling
// setTimeout.
// Do the stuff you need and then, if monitor is
// enabled create an event and dispatch (send) it.
function loop() {
/* ... main stuff ... */
// do we monitor?
if (isMonitoring) {
// something need to be updated on monitor so
// create an event
var myEvent = new CustomEvent('monitor', {
detail: {
/* here you can provide needed data for monitor */
"mydata": data /*, other data */
},
/* If you don't need to send any data in particular,
just leave detail empty like this:
detail: {},
*/
bubbles: false,
cancelable: true
});
// send event to anyone who listens..
window.dispatchEvent(myEvent);
}
//here you can use a use a flag to stop the loop,
//f.ex. if 'isLooping' === true then setTimeout...
armingloop = setTimeout(loop, 3000);
}
function toggleMonitor() {
// Call this from the toggle button, or modify to
// reflect checkbox-status etc...
isMonitoring = !isMonitoring;
}
//start everything:
loop();
I changed the example a bit from setInterval
to setTimeout
to avoid stacking/blocking. Also keep in mind that Javascript is single-threaded (with a few exceptions that are not relevant here). For this reason setTimeout
is a better choice (call it from inside the loop).
Upvotes: 3