Reload Automatico without being precise

Asked

Viewed 54 times

2

I have a question! I have a voting system, which has a page that shows the results live from the vote, this page uses to show the charts Google Charts and background has an ajax code that runs every 1 second, that is always going to the archive . xml fetch the data of the votes, but every time it updates a slight blink in the Chart, and I create that only flashed when there are updates in the number of votes!

Can someone help me solve this problem?

Codigo js:

window.setInterval(ajax, 1000);
function ajax() {
var ajax = new XMLHttpRequest();
 ajax.onreadystatechange = function(){
  if(ajax.readyState == 4 && ajax.status == 200){
  var res = ajax.responseXML;
  var xml = this;
  var votos1 = res.getElementsByTagName("votos")[0].firstChild.nodeValue;
  var votos2 = res.getElementsByTagName("votos")[1].firstChild.nodeValue;
  var votos3 = res.getElementsByTagName("votos")[2].firstChild.nodeValue;
  var votos4 = res.getElementsByTagName("votos")[3].firstChild.nodeValue;
  grafico(votos1, votos2, votos3, votos4);
  }
 }
  ajax.open("POST", "votos.xml");
  ajax.send(null);
 }

 function grafico(votos1, votos2, votos3, votos4){
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
  ['', 'Numero de Votos'],
  ['Opção 1', votos1],
  ['Opção 2', votos2],
  ['Opção 3', votos3],
  ['Opção 4', votos4]
]);
var options = {
  chart: {
    title: 'Total Votações',
    subtitle: 'Ajuda: Publico',
  },
  bars: 'vertical'
};
var chart = new google.charts.Bar(document.getElementById('grafico'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}  
}

XML structure:

<geral>
   <opcao1>
      <votos>5</votos>
      <correta>true</correta>
   </opcao1>
   <opcao2>
      <votos>10</votos>
      <correta>false</correta>
   </opcao2>
   <opcao3>
      <votos>1</votos>
      <correta>false</correta>
   </opcao3>
   <opcao4>
      <votos>20</votos>
      <correta>false</correta>
   </opcao4>
</geral>

2 answers

2

First a suggestion to work better with Ajax that is in "loop", change setInterval for setTimeout, so will not conflict two requests at the same time, because the setInterval does not wait for the request to finish which may be likely to be multiple requests at the same time, with setTimeout within the if(ajax.readyState == 4 && ajax.status == 200){ will work better.

About checking whether or not there were changes you will need to create variables to keep the values (as if it were a "cache") and check them in the next Ajax request, for example:

Note: I have identified your code to make it easier to understand

//Esta variavel servirá para manter um "cache" dos resultados
var cacheVotos = {
    'votos1': 0,
    'votos2': 0,
    'votos3': 0,
    'votos4': 0
};

function ajax() {
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function() {
        if (ajax.readyState == 4) {
            if (ajax.status == 200) {
                var res = ajax.responseXML;
                var xml = this;
                var votos1 = res.getElementsByTagName("votos")[0].firstChild.nodeValue;
                var votos2 = res.getElementsByTagName("votos")[1].firstChild.nodeValue;
                var votos3 = res.getElementsByTagName("votos")[2].firstChild.nodeValue;
                var votos4 = res.getElementsByTagName("votos")[3].firstChild.nodeValue;

                //Se qualquer um deles mudar então grafico() é chamado, caso contrário não
                if (
                    cacheVotos.votos1 != votos1 ||
                    cacheVotos.votos2 != votos2 ||
                    cacheVotos.votos3 != votos3 ||
                    cacheVotos.votos4 != votos4
                ) {
                    //Atualiza os valores do "cache"
                    cacheVotos.votos1 = votos1;
                    cacheVotos.votos2 = votos2;
                    cacheVotos.votos3 = votos3;
                    cacheVotos.votos4 = votos4;

                    grafico(votos1, votos2, votos3, votos4);
                }
            }

            //Isto irá chamar novamente o Ajax após a requisição ter sido concluida
            setTimeout(ajax, 1000);
        }
    }
    ajax.open("POST", "votos.xml");
    ajax.send(null);
}

//Inicia a função
ajax();

function grafico(votos1, votos2, votos3, votos4) {
    google.charts.load('current', {
        'packages': ['bar']
    });
    google.charts.setOnLoadCallback(drawChart);

    function drawChart() {
        var data = google.visualization.arrayToDataTable([
            ['', 'Numero de Votos'],
            ['Opção 1', votos1],
            ['Opção 2', votos2],
            ['Opção 3', votos3],
            ['Opção 4', votos4]
        ]);
        var options = {
            chart: {
                title: 'Total Votações',
                subtitle: 'Ajuda: Publico',
            },
            bars: 'vertical'
        };
        var chart = new google.charts.Bar(document.getElementById('grafico'));
        chart.draw(data, google.charts.Bar.convertOptions(options));
    }
}

1


You can create a simple variable to save concatenated values and on the return of Ajax check if there has been a change. Ex.:

var voTos;
function ajax() {...

var votosAjax = votos1.concat(votos2, votos3, votos4);
// ficará: votosAjax = "510120"

So whenever this string is different from the variable voTos, you call the function that updates the chart and also updates the value of voTos:

if(votosAjax != voTos){
   voTos = votosAjax;
   grafico(votos1, votos2, votos3, votos4);
}

As stated in the other answer, it is also important to use setTimeout() only after the return of Ajax, and not setInterval as it was done.

The code would look like this:

var voTos; // para guardar os valores vindos do Ajax
function ajax() {
   var ajax = new XMLHttpRequest();
   ajax.onreadystatechange = function(){
      if(ajax.readyState == 4 && ajax.status == 200){
         var res = ajax.responseXML;
         var xml = this;
         var votos1 = res.getElementsByTagName("votos")[0].firstChild.nodeValue;
         var votos2 = res.getElementsByTagName("votos")[1].firstChild.nodeValue;
         var votos3 = res.getElementsByTagName("votos")[2].firstChild.nodeValue;
         var votos4 = res.getElementsByTagName("votos")[3].firstChild.nodeValue;

         // valores concatenados vindos do Ajax
         var votosAjax = votos1.concat(votos2, votos3, votos4);

         // verifico se é diferente para chamar a função do gráfico
         if(votosAjax != voTos){
            voTos = votosAjax; // se for diferente, atualizo a variável
            grafico(votos1, votos2, votos3, votos4);
         }

         setTimeout(ajax, 1000);
      }
   }
   ajax.open("POST", "votos.xml");
   ajax.send(null);
}

function grafico(votos1, votos2, votos3, votos4){
   google.charts.load('current', {'packages':['bar']});
   google.charts.setOnLoadCallback(drawChart);
   function drawChart() {
      var data = google.visualization.arrayToDataTable([
      ['', 'Numero de Votos'],
      ['Opção 1', votos1],
      ['Opção 2', votos2],
      ['Opção 3', votos3],
      ['Opção 4', votos4]
      ]);
      var options = {
         chart: {
            title: 'Total Votações',
            subtitle: 'Ajuda: Publico',
         },
         bars: 'vertical'
      };
      var chart = new google.charts.Bar(document.getElementById('grafico'));
      chart.draw(data, google.charts.Bar.convertOptions(options));
   }  
}

$(document).ready(function(){
   ajax(); // chama a função
});

Browser other questions tagged

You are not signed in. Login or sign up in order to post.