If inside the loop does not work correctly

0

Good evening. I have the following function:

function verificaOnOff(){

  for(var i in tbModulos){

    var mod = tbModulos[i];

    $.get('http://'+ mod.ip +'/rele', function(data) {
        if (data == '1') {
          $('#icone-'+i).removeClass('branco');
          $('#icone-'+i).addClass('amarelo');
          $('input[id="'+i+'"]').prop('checked', true);
        } else {
          $('#icone-'+i).removeClass('amarelo');
          $('#icone-'+i).addClass('branco');
          $('input[id="'+i+'"]').prop('checked', false);
        }
    })
  }
}

It, when called, checks whether a relay is on or off, via GET (0 or 1). If you get 1, change some CSS parameters, and vice versa.

The problem is, you are only changing the latter. Where am I going wrong?

    
asked by anonymous 30.06.2018 / 01:17

1 answer

3

This may have happened because the reference of i will be the same for all requests. Since they are asynchronous requests, the loop will end quickly, reaching the maximum value of i , which in this case must be 1, before the requests are completed; so when they are completed the callback function will be called, all with the value of i equal to 1. To get around this, you will have to create different references to the value of i for each request . The easiest way to do this is to import it into a single scope of each request, within a function:

function rele(modulo, i) {
    return $.get('http://'+ modulo.ip +'/rele', function(data) {
        const icone = $('#icone-'+i)
        const isOn = (data == '1')

        icone.removeClass(isOn ? 'branco' : 'amarelo');
        icone.addClass(isOn ? 'amarelo' : 'branco')
        $('input[id="'+i+'"]').prop('checked', isOn);
    })
}

function verificaOnOff(modulos){
    $.each(modulos, (i, modulo) => rele(modulo, i));
}

Thus, the value of i of each request will be limited by the scope of the rele function, unique to each. In addition, some other improvements have been made to the code.

Instead of adding and removing classes, why not use a data-attribute ? With even CSS you can customize the elements according to the value of the attribute. Here's an example:

$('[data-status]').on('click', function (event) {
  const newStatus = ($(this).attr('data-status') == '0') ? '1' : '0'
  $(this).attr('data-status', newStatus)
});
li {
  cursor: pointer;
}

li[data-status='0'] {
  color: lightgray;
}

li[data-status='1'] {
  color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><ul><lidata-status='0'>Item1</li><lidata-status='0'>Item2</li><lidata-status='0'>Item3</li><lidata-status='0'>Item4</li><lidata-status='0'>Item5</li></ul>

Soyourcodewouldlooksomethinglike:

functionrele(modulo,i){return$.get('http://'+modulo.ip+'/rele',function(data){$('#icone-'+i).attr('data-status',data)$('input[id="'+i+'"]').prop('checked', data == '1');
    })
}

What simplifies it a little.

    
30.06.2018 / 02:01