2

我有 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的状态更新功能受到了影响(例如状态回复被错误的元素捕获。)monitoringbigloop

请注意,我也有一个setTimer

我的问题是,我怎样才能确保任何 2 setIntervals 被隔离并且不会相互影响?

4

3 回答 3

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();

我稍微更改了示例setIntervalsetTimeout避免堆叠/阻塞。还要记住,Javascript 是单线程的(这里有一些不相关的例外)。出于这个原因,这setTimeout是一个更好的选择(从循环内部调用它)。

于 2013-05-16T08:27:25.410 回答
1

如何确保任何 2 个 setIntervals 是隔离的并且不会相互影响?

变量范围

确保所涉及的所有变量都具有正确的范围,并避免将任何变量添加到全局范围中,除非它是完全不可避免的(这不应该是这种情况)。这意味着您在var声明任何变量时都希望使用关键字。

如果您的变量被正确地限定在它们各自setInterval的调用范围内,那么即使您使用了相同的变量名,也没有一个影响另一个值的危险。

检查你的逻辑

如果您要查询然后修改页面上的同一组元素,那么它们就不能独立,因为其中一个的更改将反映在另一个的下一次执行中。任何共享逻辑、任何全局变量的使用等都是要引入问题的潜在候选对象。

本质上,您正在寻找两者之间的任何重叠,然后(希望)消除它。如果不能消除,那么你的两个 setIntervals 就不能被隔离,你要么必须接受两者是相互联系的,要么找到另一种解决问题的方法。

于 2013-05-16T09:27:28.023 回答
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
});
于 2013-05-16T08:00:05.003 回答