我有2个setInterval函数(好吧,伙计们,对不起,我认为里面的代码可能是多余的,会让问题变得本地化:/但无论如何,这里是:
$('#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);
});
和
$('#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);
}
两者都将由不同的选择器触发。我观察到,当bigloop
被激活,并且armingloop
稍后也被激活时,monitoring
中的状态更新功能bigloop
会受到影响(例如状态回复是被错误的元素捕获。)
请注意,我也有setTimer
。
我的问题是,如何确保任何2 setInterval
被隔离并且不会相互影响?
答案 0 :(得分:3)
你根本不能,因为他们不保证订单。它们与其他事件(包括重绘等)一起被添加到事件队列中,并且首先调用它们。
更好的实现是在你的主循环中抛出你的监听器正在监听的CustomEvent
。
简化为:
// 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();
我将示例从setInterval
更改为setTimeout
以避免堆叠/阻止。还要记住,Javascript是单线程的(除了一些与此无关的例外)。因此setTimeout
是更好的选择(从循环内部调用它)。
答案 1 :(得分:1)
如何确保任何2个setIntervals被隔离并且不会相互影响?
可变范围
确保所涉及的所有变量都是正确的范围,并避免将任何变量添加到全局范围,除非它完全不可避免(这不应该是这种情况)。这意味着每当您声明任何变量时,您都希望使用var
关键字。
如果你的变量被正确地限定为各自的setInterval
调用,那么即使你使用了相同的变量名,也不存在影响另一个变量值的危险。
检查您的逻辑
如果您在两个页面中查询并修改相同的元素集,那么它们就不能独立,因为其中一个元素的更改将反映在另一个元素的下一个执行中一。任何共享逻辑,全局变量的使用等都是引入问题的潜在候选者。
基本上你正在寻找两者之间的任何重叠,然后(希望)消除它。如果不能被删除,那么你的两个setIntervals就无法被隔离,你要么必须接受这两者是联系的,要么找到解决问题的另一种方法。
答案 2 :(得分:0)
如何触发间隔?
也许您可以尝试将它们称为例如点击功能:
$('<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
});