Pergunta

Eu uso jQuery. E eu não quero chamadas AJAX paralelas no meu aplicativo, cada chamada deve esperar o anterior antes de iniciar. Como implementá-lo? Há qualquer ajudante?

Atualizar Se houver qualquer versão síncrona do XMLHttpRequest ou jQuery.post eu gostaria de saber. Mas seqüencial! = Síncrono, e eu gostaria de uma solução assíncrona e seqüencial.

Foi útil?

Solução

Há uma maneira muito melhor de fazer isso do que usando chamadas ajax síncronos. AJAX jQuery retorna um adiada para que você pode simplesmente usar o tubo de encadeamento para se certificar de que cada ajax acabamentos chamada antes das próximas corridas. Aqui está um exemplo de trabalho com um exemplo mais aprofundada pode jogo com on jsFiddle.

// How to force async functions to execute sequentially 
// by using deferred pipe chaining.

// The master deferred.
var dfd = $.Deferred(),  // Master deferred
    dfdNext = dfd; // Next deferred in the chain
    x = 0, // Loop index
    values = [], 

    // Simulates $.ajax, but with predictable behaviour.
    // You only need to understand that higher 'value' param 
    // will finish earlier.
    simulateAjax = function (value) {
        var dfdAjax = $.Deferred();

        setTimeout(
            function () {
                dfdAjax.resolve(value);
            },
            1000 - (value * 100)
        );

        return dfdAjax.promise();
    },

    // This would be a user function that makes an ajax request.
    // In normal code you'd be using $.ajax instead of simulateAjax.
    requestAjax = function (value) {
        return simulateAjax(value);
    };

// Start the pipe chain.  You should be able to do 
// this anywhere in the program, even
// at the end,and it should still give the same results.
dfd.resolve();

// Deferred pipe chaining.
// What you want to note here is that an new 
// ajax call will not start until the previous
// ajax call is completely finished.
for (x = 1; x <= 4; x++) {

    values.push(x);

    dfdNext = dfdNext.pipe(function () {
        var value = values.shift();
        return requestAjax(value).
            done(function(response) {
                // Process the response here.

            });

    });

}

Algumas pessoas têm comentado que eles não têm idéia de que o código faz. Para entender isso, você primeiro precisa entender promessas de JavaScript. Tenho a certeza promessas estão prestes a ser um recurso de linguagem javascript nativa, de modo que deve dar-lhe um bom incentivo para aprender.

Outras dicas

Você tem duas opções que eu posso pensar. Um deles é a cadeia-los através de chamadas de retorno. A outra é fazer com que as chamadas síncronas em vez de assíncrona.

Existe uma razão que você quer que eles seqüencial? Isso vai retardar as coisas.

Para fazer o síncrona chamada, você vai definir a opção async na chamada Ajax para falso. Consulte a documentação em http://docs.jquery.com/Ajax/jQuery.ajax#options (clique opções de guia para vê-los).

Você poderia dar narrativa javascript uma tentativa http://www.neilmix.com/narrativejs/doc /

Eu nunca usei-me embora. Se eu quisesse fazer isso, eu iria configurar algum tipo de abstração para encadeamento de ações assíncronas. Como já foi dito, a versão Síncrono dos ajax objeto bloqueia eventos sejam processados ??enquanto ele está à espera de uma resposta. Isso faz com que o navegador para olhar como ele está congelado até que ele recebe uma resposta.

A melhor maneira que você poderia fazer isso é por encadeamento retornos de chamada como disse Nosredna. Eu não recomendo o uso de XMLHttpRequest síncrona como eles bloquear o aplicativo inteiro.

Há não muito ajudante para este, tanto quanto eu sei, mas você poderia fazer algo parecido com um callback FIFO.

Olhe para isto: http://docs.jquery.com/Ajax/jQuery.ajax (clique na guia "opções").

Mas lembre-se uma chamada síncrona irá congelar a página até a resposta é recebida, por isso não pode ser usado em um site de produção, porque os usuários vai ficar bravo se por algum motivo eles têm que esperar 30 segundos com o seu navegador congelado.

EDIT: ok, com sua atualização é mais claro o que você quer alcançar;)

Assim, seu código pode ser parecido com isto:

    $.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);
            });
        });
    });

Desta forma, a segunda chamada só será emitido quando a resposta à primeira chamada foi recebida e processada, e a terceira chamada só será emitido quando a resposta à segunda chamada foi recebida e processada. Este código é para getJSON mas pode ser adaptado para $ .ajax.

Defina o assíncrono opção para falsa, por exemplo.,

$.ajax({ async: false /*, your_other_ajax_options_here */ });

Referência: Ajax / jQuery.ajax

chamadas síncronas não são necessariamente mais lento, se você tiver um aplicativo onde AJAX chama aberta, as mensagens para, em seguida, fecha um socket, várias chamadas à tomada não fazem sentido como alguns soquetes só pode lidar com uma única conexão, em nesse caso, filas de dados para que seu único enviado quando a chamada AJAX anterior completou meios muito mais elevada taxa de transferência de dados.

(async () => { 
  for(f of ['1.json','2.json','3.json']){
    var json = await $.getJSON(f);
    console.log(json)
 };
})()
  1. solicita 3 arquivos JSON com chamadas ajax jQuery
  2. processo em sequência (e não em paralelo) com Await
  3. funciona no Chrome / Firefox / Edge (a partir de 2018/01/30)

MDN

Você pode usar promessa de fazer chamadas Ajax seqüencial. Usando impulso matriz e pop método promessa, chamadas ajax sequenciais será muito mais fácil.

var promises = [Promise.resolve()];

function methodThatReturnsAPromise(id) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: 'https://jsonplaceholder.typicode.com/todos/'+id,
      dataType:'json',
      success: function(data)
      {
        console.log("Ajax Request Id"+id);
        console.log(data);
        resolve();
      }
    });
  });
} 

function pushPromise(id)
{
  promises.push(promises.pop().then(function(){
    return methodThatReturnsAPromise(id)}));
}


pushPromise(1);
pushPromise(3);
pushPromise(2);

Que tal usar eventos Node.js?

var EventEmitter = require('events').EventEmitter;
var eventEmitter = new EventEmitter();
var $ = require('jquery');

var doSomething = function (responseData) {
  var nextRequestData = {};
  // do something with responseData
  return nextRequestData;
};

// ajax requests
var request1 = $.ajax;
var request2 = $.ajax;
var requests = [request1, request2];

eventEmitter.on('next', function (i, requestData) {
  requests[i](requestData).then(
    function (responseData) {
      console.log(i, 'request completed');
      if (i+1 < requests.length) {
        var nextRequestData = doSomething(responseData);
        eventEmitter.emit('next', i+1, nextRequestData);
      }
      else {
        console.log('completed all requests');
      }
    },
    function () {
      console.log(i, 'request failed');
    }
  );
});

var data = {
  //data to send with request 1
};
eventEmitter.emit('next', 0, data);

seqüencial! = Síncrono, e eu gostaria de uma solução assíncrona e seqüencial

execução síncrona geralmente significa "usando o mesmo relógio", enquanto que os meios de execução sequenciais "seguinte na ordem ou sequência de".

Para o seu caso de uso específico Acho que devem ser cumpridas ambas as condições, como a execução assíncrona implica a possibilidade de um resultado não-seqüencial.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top