Subsequent Calls in Ajax

8

I wrote a system on Web2py to a client, and he wanted me to automate a procedure. I thought about using Ajax. The idea is as follows:

I have a list of companies. Let's say, 50. I want the screen to open with the list of companies and, on top of them, that has a "Start" button. When I click "Start," the page sends the server an Ajax request asking it to perform a calculation for the first company. This is done because it's a heavy calculation, and leaving everything in a request would cause nginx to return a timeout and the calculation would not go through.

I already know how to update the status on the screen. Now comes my doubt.

After the calculation of the first company, the calculation of the second company is automatically called. After the second, the calculation of the third, and so on, is called until the calculation of the others is completed:

Empresa 1: Ok!
Empresa 2: Ok!
Empresa 3: Processando...
Empresa 4: Aguardando...
...

The idea is that I can also pass some parameters beyond the company code, such as a date range, to the calculation.

How can I do this? Should I use pure Ajax or can I use a JS package for this?

    
asked by anonymous 16.12.2014 / 21:15

4 answers

6

I would use async since you are willing to use an external library

$(function() {
  async.eachSeries($('td.usuario').toArray(), function(td, cb) {
    var $td = $(td);

    $.ajax({
        url: 'suaUrl',
    }).done(function(data) {
        cb(); //Use o objeto $td para alterar o status (.siblings('td'))
    }).fail(function() {
        cb(new Error('ops!'));
    });

  }, function(err) {
      if(err) {
          console.log('Algo deu errado...')
      }

      console.log('FIM!');
  });
});

HTML would look something like this.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><scriptsrc="http://cdnjs.cloudflare.com/ajax/libs/async/0.9.0/async.js"></script>

<table>
  <tr>
    <td class="usuario" data-user="101">Fulano</td>  
    <td>Aguardando...</td>  
  </tr>
  <tr>
    <td class="usuario" data-user="129">Ciclano</td>  
    <td>Aguardando...</td>  
  </tr>
  <tr>
    <td class="usuario" data-user="74">Beltrano</td>  
    <td>Aguardando...</td>  
  </tr>  
  <tr>
    <td class="usuario" data-user="2056">Asnésio</td>  
    <td>Aguardando...</td>  
  </tr>  
</table>
    
16.12.2014 / 21:43
5

Assuming all your elements are siblings (several% s of% s for example, or rows of a table) you can make the ajax call on the first one and - upon completing it - move on next until not on any more :

$("#meuid li:eq(0)").each(function processar() {
    var $this = $(this);
    var parametros = $(...)...;
    var idEmpresa = $this.data("empresa");
    $.get(url, params, function(dados) {
        // Tratar dos dados
        $this.next("li:eq(0)").each(processar); // O each se encarrega da condição de parada
    });                                         // quando o next não retornar nenhum elemento
});

Here when I use li in the :eq(0) selector, I guarantee that at most a single element will be returned. Zero if there is none, and one if there is. The next call is for convenience, so you could simply use a function with a parameter.

    
16.12.2014 / 21:56
2

Normally I would run an accountant and run the entire list until it reaches the total number of companies:

var lista = $('.lista').find('li');
function calcular(loop){
    if (loop <= lista.length){
        var empresa = $('.lista').find('li:eq('+loop+')');
        $.getJSON(empresa.data('url'), function(data) {
           calcular(loop+1);
        }
    }
}
calcular(0);
    
16.12.2014 / 23:19
1

Pure Ajax can solve your problem. The term varia - cascading calls or sequential async calls :

$.getJSON("http://example.com/jsoncall", function(data) {
        process(data);
        $.getJSON("http://example.com/jsoncall2", function (data) {
            processAgain(data);
            $.getJSON("http://example.com/anotherjsoncall", function(data) {
                processAgainAndAgain(data);
            });
        });
    });

In this case, you are responsible for securing chaining in case something goes wrong.

Via AngularJS is even easier:

$q.all([asyncCall1(), asyncCall2() .....])
    
16.12.2014 / 21:39