Aguarde até que todas as solicitações jQuery Ajax sejam concluídas?

675

Como faço para uma função esperar até que todas as solicitações jQuery Ajax sejam feitas dentro de outra função?

Em resumo, preciso aguardar que todas as solicitações do Ajax sejam feitas antes de executar a próxima. Mas como?

jamietelin
fonte
Como você está chamando seus pedidos originais de ajax?
NakedBrunch 14/09/10
2
O que você quer dizer com "pronto"? Entendo que "todas as solicitações foram concluídas com êxito ou não" (resolvidas ou rejeitadas). Mas você pode querer dizer "todas as solicitações foram concluídas com êxito" (resolvidas). veja todas as variações em api.jquery.com/category/deferred-object
Adrien Seja

Respostas:

911

O jQuery agora define uma função when para esse propósito.

Ele aceita qualquer número de objetos adiados como argumentos e executa uma função quando todos eles forem resolvidos.

Isso significa que, se você deseja iniciar (por exemplo) quatro solicitações ajax, execute uma ação quando elas forem concluídas, você pode fazer algo assim:

$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
    // the code here will be executed when all four ajax requests resolve.
    // a1, a2, a3 and a4 are lists of length 3 containing the response text,
    // status, and jqXHR object for each of the four ajax calls respectively.
});

function ajax1() {
    // NOTE:  This function must return the value 
    //        from calling the $.ajax() method.
    return $.ajax({
        url: "someUrl",
        dataType: "json",
        data:  yourJsonData,            
        ...
    });
}

Na minha opinião, cria uma sintaxe limpa e clara e evita o envolvimento de variáveis ​​globais como ajaxStart e ajaxStop, que podem ter efeitos colaterais indesejados à medida que a página se desenvolve.

Se você não sabe de antemão quantos argumentos ajax precisa esperar (ou seja, deseja usar um número variável de argumentos), isso ainda pode ser feito, mas é um pouco mais complicado. Consulte Passar em uma matriz de adiados para $ .when () (e talvez jQuery .when ao solucionar problemas com número variável de argumentos ).

Se você precisar de um controle mais profundo sobre os modos de falha dos scripts ajax, etc., poderá salvar o objeto retornado .when()- é um objeto jQuery Promise que abrange todas as consultas ajax originais. Você pode ligar .then()ou .fail()nele para adicionar manipuladores detalhados sucesso / fracasso.

Alex
fonte
46
Isso deve ser marcado como uma resposta correta, porque é simples, eficiente e funciona muito bem. Além disso, deve-se notar que $.whenretorna um Promiseobjeto que possui métodos mais úteis, não apenas .done. Por exemplo, com o .then(onSuccess, onFailure)método, você pode reagir quando as duas solicitações forem bem-sucedidas ou pelo menos uma delas falhar.
skalee
2
É possível agrupar os pedidos ajax1..4 em uma matriz e passar isso?
andig 5/05
33
Tenha cuidado com o failcaso. Ao contrário done, os faildisparos imediatamente na primeira falha e desconsideram os demais adiados.
Ryan Mohr
1
@skalee, obrigado por destacar o fato de que uma onFailurefunção pode ser anexada. Como indiquei em um comentário à pergunta do OP: ele pode querer indicar com mais precisão o que ele quis dizer com "pronto". "Ryan Mohr" também tinha um ponto muito bom sobre o fato de que failse comporta de forma diferente como done, alguns mais leitura a ser feito sobre PromisesAcho html5rocks.com/en/tutorials/es6/promises
Adrien Seja
1
É ótimo dar às pessoas exposição ao método when e às promessas em geral, mas acho que essa não é a melhor resposta. Se algum desses ajax funcionar em qualquer parte da linha, crie outra solicitação ajax e não integre essa nova promessa à cadeia corretamente ... essas solicitações escaparão dessa técnica. Por exemplo, não posso usar essa técnica sem modificar a biblioteca do Shopify que estou usando para o comportamento de adicionar ao carrinho do ajax, porque não foi gravada de maneira 'promissora' e nunca retorna os objetos xhr criados. Isso faz sentido? Ainda é uma ótima resposta!
Ziggy
292

Se você quiser saber quando todas as ajax solicitações foram concluídas no seu documento, não importa quantas delas existam, basta usar o evento $ .ajaxStop desta maneira:

$(document).ajaxStop(function () {
  // 0 === $.active
});

Nesse caso, você não precisa adivinhar quantas solicitações estão acontecendo no aplicativo, que podem terminar no futuro, nem se aprofundar nas funções de lógica complexa ou descobrir quais funções estão fazendo HTTP(S)solicitações.

$.ajaxStopaqui também pode ser associado a qualquer HTMLnó que você acha que pode ser modificado pelo requst.


Atualização:
se você deseja manter a ESsintaxe, pode usar Promise.all para ajaxmétodos conhecidos :

Promise.all([ajax1(), ajax2()]).then(() => {
  // all requests finished successfully
}).catch(() => {
  // all requests finished but one or more failed
})

Um ponto interessante aqui é que ele trabalha com Promisese $.ajaxsolicita.

Aqui está a demonstração do jsFiddle .


Atualização 2:
versão ainda mais recente usando a sintaxe assíncrona / aguardada :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }
Arsen Khachaturyan
fonte
16
+1 Muito melhor do que outras respostas , caso você precise lidar com scripts de terceiros com retornos / chamadas anônimas.
Kaiser #
5
@ Kaiser Ponto válido, mas não é o que a pergunta estava fazendo. Não é muito bom se você não quiser esperar que todas as chamadas AJAX retornem. A questão é específica sobre aguardar as chamadas AJAX que você fez por si mesmo (chamadas dentro de outra função, como o OP escreveu). Algum outro código pode ter feito outra chamada AJAX que você não deseja esperar.
Juan Mendes
6
Comparado à solução when (), ele tem a vantagem de funcionar mesmo que o número de chamadas ajax não seja conhecido.
Alexis Dufrenoy
5
Comparado à solução when (), possui a grande desvantagem de não funcionar bem em conjunto com outros componentes, pois compartilha um estado global em todo o documento. Se houver alguma pesquisa longa acontecendo continuamente, talvez nunca seja acionada.
Bergi 27/07/2014
3
Você é @AdrienBe não é correto, ajaxStop lida com todas as solicitações de ajax não importa o que eles fazem sucesso ou não, apenas como prova das minhas palavras olhar para este jsfiddle.net/36votxba/2
Arsen Khachaturyan
32

Eu encontrei uma boa resposta por gnarf my self, que é exatamente o que eu estava procurando :)

jQuery ajaxQueue

//This handles the queues    
(function($) {

  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {

    var oldComplete = ajaxOpts.complete;

    ajaxQueue.queue(function(next) {

      ajaxOpts.complete = function() {
        if (oldComplete) oldComplete.apply(this, arguments);

        next();
      };

      $.ajax(ajaxOpts);
    });
  };

})(jQuery);

Em seguida, você pode adicionar uma solicitação ajax à fila como esta:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
jamietelin
fonte
37
Parece que você esqueceu de atribuir a esta resposta adequadamente , eu a adicionei.
Tim Post
21

Use o ajaxStopevento.

Por exemplo, digamos que você tenha uma mensagem carregando ... enquanto busca 100 solicitações ajax e deseja ocultar essa mensagem depois de carregada.

No documento jQuery :

$("#loading").ajaxStop(function() {
  $(this).hide();
});

Observe que ele aguardará todas as solicitações de ajax serem feitas nessa página.

olafure
fonte
5
Isso pressupõe que você sabe que não haverá quaisquer outras solicitações de AJAX na página, não uma muito boa suposição
Juan Mendes
A partir do jQuery 1.8, o método .ajaxStop () deve ser anexado apenas ao documento.
Geomorillo
1
Corrija-me se eu estiver errado, mas isso não transformará seu projeto em um site de "formulários da web da velha escola"? Quero dizer, se sua página inteira precisa aguardar uma solicitação antes que ela possa continuar, qual é o sentido da solicitação do ajax em primeiro lugar?
BillRuhl
@BillRuhl, no nosso caso, estou percorrendo uma coleção jquery para criar coisas novas e preciso saber sobre toda a coleção quando terminar, antes de fazer alguns ajustes no layout. Não parece um caso particularmente incomum. Seria ruim se um monte de outras coisas do ajax estivesse em processo, mas não estará aqui.
eon
21

NOTA: As respostas acima usam funcionalidades que não existiam no momento em que essa resposta foi escrita. Eu recomendo usar jQuery.when()essas abordagens, mas estou deixando a resposta para fins históricos.

-

Você provavelmente poderia se dar bem com um semáforo de contagem simples, embora a maneira como você o implemente dependa do seu código. Um exemplo simples seria algo como ...

var semaphore  = 0,     // counting semaphore for ajax requests
    all_queued = false; // bool indicator to account for instances where the first request might finish before the second even starts

semaphore++;
$.get('ajax/test1.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test2.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test3.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test4.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

// now that all ajax requests are queued up, switch the bool to indicate it
all_queued = true;

Se você quiser que isso funcione como {async: false}, mas não queira bloquear o navegador, poderá realizar o mesmo com uma fila jQuery.

var $queue = $("<div/>");
$queue.queue(function(){
    $.get('ajax/test1.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test2.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test3.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test4.html', function(data) {
        $queue.dequeue();
    });
});
BBonifield
fonte
10
Parece que isso complicaria demais um problema trivial.
Chris
2
Realmente não é tão complicado assim. A contagem de semáforos é um mecanismo comum no CS. Se você preferir, o exemplo usando filas jQuery também funcionaria sem a necessidade de implementar o semáforo.
BBonifield
1
Não vejo um problema com o contador de semáforo, no entanto, vejo um problema com a ideia de ter QUATRO funções para manipular o retorno de chamada resultante. Você deve definir uma função primeiro e depois referenciá-la em cada uma .get(). Dessa forma, pelo menos você não duplica esse código. Não apenas isso, mas declarar function(){}cada vez aloca memória cada vez! Em vez disso, é uma prática ruim se você puder chamar uma função definida estaticamente.
Alexis Wilke
1
@AlexisWilke Esta é uma resposta de 4,5 anos e deveria ser um exemplo de como os semáforos e as filas funcionam. Você está pensando um pouco demais sobre isso, e não acho que a CAPITALIZAÇÃO PARA FAZER UM PONTO seja necessária.
BBonifield
2
Bem ... não fui eu quem deu -1 ... e entendo que as respostas tendem a envelhecer. No entanto, as pessoas continuam a encontrá-las e, até onde eu sei, não é proibido fornecer informações a pessoas que potencialmente as usarão ainda hoje.
Alexis Wilke
8

O javascript é baseado em eventos; portanto, você nunca deve esperar ; em vez disso, defina ganchos / retornos de chamada

Provavelmente, você pode apenas usar os métodos de sucesso / completo do jquery.ajax

Ou você pode usar .ajaxComplete :

$('.log').ajaxComplete(function(e, xhr, settings) {
  if (settings.url == 'ajax/test.html') {
    $(this).text('Triggered ajaxComplete handler.');
    //and you can do whatever other processing here, including calling another function...
  }
});

embora você deva postar um pseudocódigo de como suas solicitações ajax são chamadas para serem mais precisas ...

Stefano
fonte
8

Uma pequena solução alternativa é algo como isto:

// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});

A esperança pode ser útil ...

Jesfre
fonte
Embora as outras respostas sejam tecnicamente melhores, já que é muito mais fácil de entender, eu realmente gosto dessa. Agradável!
Jay
4

O jQuery permite especificar se você deseja que a solicitação ajax seja assíncrona ou não. Você pode simplesmente tornar as solicitações ajax síncronas e o restante do código não será executado até que retornem.

Por exemplo:

jQuery.ajax({ 
    async: false,
    //code
});
shmuel613
fonte
42
Uma coisa a observar é que o uso de {async: false} pode bloquear temporariamente o navegador. api.jquery.com/jQuery.ajax
BBonifield
30
Isso é contrário à prática padrão do jQuery / Javascript. O AJAX sempre deve ser assíncrono. Você deve usar jQuery.when ().
SystemParadox
43
É uma péssima ideia! Nunca faça isso! Bloqueio = não responde às ações do usuário, nem mesmo a rolagem ou algo assim! (Além disso, async: false vai ser depreciado em jQuery 1.8.)
skalee
5
Particularmente, se a solicitação falhar ou demorar muito por algum motivo imprevisível (o que, pela Lei de Murphy, está prestes a acontecer!), Isso geralmente é uma má ideia para o código de produção devido ao bloqueio do navegador, conforme declarado acima.
10282 Alex
27
Essa é uma péssima idéia. NÃO USE ESTA RESPOSTA.
Tauren
2

Se você precisar de algo simples; retorno de chamada único e concluído

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();
Fatmuemoo
fonte
4
pode gerar um loop sem fim!
Diego Favero
2
Este é um loop sem fim? Quando? Quando o AJAX nunca volta?
31716 Jonathan
2

Além disso, você pode usar o async.js .

Eu acho que é melhor do que $. Quando, porque você pode mesclar todos os tipos de chamadas assíncronas que não suportam promessas prontas, como tempos limite, chamadas do SqlLite etc. e não apenas solicitações de ajax.

George Mavritsakis
fonte
2

Com base na resposta do @BBonifield, escrevi uma função de utilitário para que a lógica do semáforo não seja espalhada em todas as chamadas ajax.

untilAjax é a função de utilitário que chama uma função de retorno de chamada quando todos os ajaxCalls são concluídos.

ajaxObjsé uma matriz de objetos de configuração do ajax [http://api.jquery.com/jQuery.ajax/].

fn é função de retorno de chamada

function untilAjax(ajaxObjs, fn) {
  if (!ajaxObjs || !fn) {
    return;
  }
  var ajaxCount = ajaxObjs.length,
    succ = null;

  for (var i = 0; i < ajaxObjs.length; i++) { //append logic to invoke callback function once all the ajax calls are completed, in success handler.
    succ = ajaxObjs[i]['success'];
    ajaxObjs[i]['success'] = function(data) { //modified success handler
      if (succ) {
        succ(data);
      }
      ajaxCount--;
      if (ajaxCount == 0) {
        fn(); //modify statement suitably if you want 'this' keyword to refer to another object
      }
    };
    $.ajax(ajaxObjs[i]); //make ajax call
    succ = null;
  };

Exemplo: doSomethingfunção usa untilAjax.

function doSomething() {
  // variable declarations
  untilAjax([{
    url: 'url2',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url1',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url2',
    dataType: 'json',
    success: function(response) {
      //do something with success data
    }
  }], function() {
    // logic after all the calls are completed.
  });
}
Sanjeev Kumar Dangi
fonte
2

Eu recomendo usar $ .when () se você estiver começando do zero.

Embora essa pergunta tenha mais de um milhão de respostas, ainda não encontrei nada útil para o meu caso. Digamos que você precise lidar com uma base de código existente, já fazendo algumas chamadas ajax e não queira introduzir a complexidade das promessas e / ou refazer tudo.

Podemos facilmente tirar proveito do jQuery .data, .one .triggerfunções que têm sido uma parte do jQuery desde sempre.

Codepen

O lado bom da minha solução é:

  • é óbvio do que o retorno de chamada depende exatamente

  • a função triggerNowOrOnLoadednão se importa se os dados já foram carregados ou ainda estamos esperando por eles

  • é super fácil conectá-lo a um código existente

$(function() {

  // wait for posts to be loaded
  triggerNowOrOnLoaded("posts", function() {
    var $body = $("body");
    var posts = $body.data("posts");

    $body.append("<div>Posts: " + posts.length + "</div>");
  });


  // some ajax requests
  $.getJSON("https://jsonplaceholder.typicode.com/posts", function(data) {
    $("body").data("posts", data).trigger("posts");
  });

  // doesn't matter if the `triggerNowOrOnLoaded` is called after or before the actual requests 
  $.getJSON("https://jsonplaceholder.typicode.com/users", function(data) {
    $("body").data("users", data).trigger("users");
  });


  // wait for both types
  triggerNowOrOnLoaded(["posts", "users"], function() {
    var $body = $("body");
    var posts = $body.data("posts");
    var users = $body.data("users");

    $body.append("<div>Posts: " + posts.length + " and Users: " + users.length + "</div>");
  });

  // works even if everything has already loaded!
  setTimeout(function() {

    // triggers immediately since users have been already loaded
    triggerNowOrOnLoaded("users", function() {
      var $body = $("body");
      var users = $body.data("users");

      $body.append("<div>Delayed Users: " + users.length + "</div>");
    });

  }, 2000); // 2 seconds

});

// helper function
function triggerNowOrOnLoaded(types, callback) {
  types = $.isArray(types) ? types : [types];

  var $body = $("body");

  var waitForTypes = [];
  $.each(types, function(i, type) {

    if (typeof $body.data(type) === 'undefined') {
      waitForTypes.push(type);
    }
  });

  var isDataReady = waitForTypes.length === 0;
  if (isDataReady) {
    callback();
    return;
  }

  // wait for the last type and run this function again for the rest of the types
  var waitFor = waitForTypes.pop();
  $body.on(waitFor, function() {
    // remove event handler - we only want the stuff triggered once
    $body.off(waitFor);

    triggerNowOrOnLoaded(waitForTypes, callback);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>Hi!</body>

cilf
fonte
2

Estou usando a verificação de tamanho quando toda a carga do ajax foi concluída

function get_ajax(link, data, callback) {
    $.ajax({
        url: link,
        type: "GET",
        data: data,
        dataType: "json",
        success: function (data, status, jqXHR) {
            callback(jqXHR.status, data)
        },
        error: function (jqXHR, status, err) {
            callback(jqXHR.status, jqXHR);
        },
        complete: function (jqXHR, status) {
        }
    })
}

function run_list_ajax(callback){
    var size=0;
    var max= 10;
    for (let index = 0; index < max; index++) {
        var link = 'http://api.jquery.com/ajaxStop/';
        var data={i:index}
        get_ajax(link,data,function(status, data){
            console.log(index)
            if(size>max-2){
                callback('done')
            }
            size++
            
        })
    }
}

run_list_ajax(function(info){
    console.log(info)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>

tranchau
fonte
perfeito para o seu exemplo.
MarwaAhmad
2

Para expandir a resposta de Alex, tenho um exemplo com argumentos e promessas variáveis. Eu queria carregar imagens via ajax e exibi-las na página depois que todas foram carregadas.

Para fazer isso, usei o seguinte:

let urlCreator = window.URL || window.webkitURL;

// Helper function for making ajax requests
let fetch = function(url) {
    return $.ajax({
        type: "get",
        xhrFields: {
            responseType: "blob"
        },
        url: url,
    });
};

// Map the array of urls to an array of ajax requests
let urls = ["https://placekitten.com/200/250", "https://placekitten.com/300/250"];
let files = urls.map(url => fetch(url));

// Use the spread operator to wait for all requests
$.when(...files).then(function() {
    // If we have multiple urls, then loop through
    if(urls.length > 1) {
        // Create image urls and tags for each result
        Array.from(arguments).forEach(data => {
            let imageUrl = urlCreator.createObjectURL(data[0]);
            let img = `<img src=${imageUrl}>`;
            $("#image_container").append(img);
        });
    }
    else {
        // Create image source and tag for result
        let imageUrl = urlCreator.createObjectURL(arguments[0]);
        let img = `<img src=${imageUrl}>`;
        $("#image_container").append(img);
    }
});

Atualizado para funcionar com URLs únicos ou múltiplos: https://jsfiddle.net/euypj5w9/

GammaGames
fonte
2

Como outras respostas mencionadas, você pode ajaxStop()aguardar até que todas as solicitações de ajax sejam concluídas.

$(document).ajaxStop(function() {
     // This function will be triggered every time any ajax request is requested and completed
});

Se você deseja fazer isso para uma ajax()solicitação específica, o melhor que pode fazer é usar o complete()método dentro de uma determinada solicitação ajax:

$.ajax({
    type: "POST",
    url: "someUrl",
    success: function(data) {
        // This function will be triggered when ajax returns a 200 status code (success)
    },
    complete: function() {
        // This function will be triggered always, when ajax request is completed, even it fails/returns other status code
    },
    error: function() {
        // This will be triggered when ajax request fail.
    }
});


Mas, se você precisar esperar apenas algumas e certas solicitações de ajax serem feitas? Use o maravilhoso javascript promete esperar até que o ajax que você deseja esperar esteja pronto. Fiz um exemplo breve, fácil e legível para mostrar como as promessas funcionam com o ajax.
Por favor, dê uma olhada no próximo exemplo . Eu costumava setTimeoutesclarecer o exemplo.

// Note:
// resolve() is used to mark the promise as resolved
// reject() is used to mark the promise as rejected

$(document).ready(function() {
    $("button").on("click", function() {

        var ajax1 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png",
                xhrFields: { responseType: 'blob'},
                success: function(data) {
                    setTimeout(function() {
                        $('#image1').attr("src", window.URL.createObjectURL(data));
                        resolve(" Promise ajax1 resolved");
                    }, 1000);
                },
                error: function() {
                    reject(" Promise ajax1 rejected");
                },
            });
        });

        var ajax2 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://cdn1.iconfinder.com/data/icons/social-media-vol-1-1/24/_github-512.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image2').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax2 resolved");
                    }, 1500);
                },
                error: function() {
                    reject(" Promise ajax2 rejected");
                },
            });
        });

        var ajax3 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/632/1*LUfpOf7teWvPdIPTBmYciA.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image3').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax3 resolved");
                    }, 2000);
                },
                error: function() {
                    reject(" Promise ajax3 rejected");
                },
            });
        });
        
        Promise.all([ajax1, ajax2, ajax3]).then(values => {
            console.log("We waited until ajax ended: " + values);
            console.log("My few ajax ended, lets do some things!!")
        }, reason => {
            console.log("Promises failed: " + reason);
        });
        
        // Or if you want wait for them individually do it like this
        // ajax1.then(values => {
        //    console.log("Promise 1 resolved: " + values)
        // }, reason => {
        //     console.log("Promise 1 failed: " + reason)
        // });
    });

});
img {
  max-width: 200px;
  max-height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Make AJAX request</button>
<div id="newContent">
    <img id="image1" src="">
    <img id="image2" src="">
    <img id="image3" src="">
</div>

Surfista Prateado
fonte
0

Eu achei uma maneira simples, usando shift()

function waitReq(id)
{
  jQuery.ajax(
  {
    type: 'POST',
    url: ajaxurl,
    data:
    {
      "page": id
    },
    success: function(resp)
    {
      ...........
      // check array length if not "0" continue to use next array value
      if(ids.length)
      {
        waitReq(ids.shift()); // 2
      )
    },
    error: function(resp)
    {
      ....................
      if(ids.length)
      {
        waitReq(ids.shift());
      )
    }
  });
}

var ids = [1, 2, 3, 4, 5];    
// shift() = delete first array value (then print)
waitReq(ids.shift()); // print 1
uingtea
fonte
0

Minha solução é a seguinte

var request;
...
'services': {
  'GetAddressBookData': function() {
    //This is the primary service that loads all addressbook records 
    request = $.ajax({
      type: "POST",
      url: "Default.aspx/GetAddressBook",
      contentType: "application/json;",
      dataType: "json"
    });
  },

  ...

  'apps': {
    'AddressBook': {
      'data': "",
      'Start': function() {
          ...services.GetAddressBookData();
          request.done(function(response) {
            trace("ajax successful");
            ..apps.AddressBook.data = response['d'];
            ...apps.AddressBook.Filter();
          });
          request.fail(function(xhr, textStatus, errorThrown) {
            trace("ajax failed - " + errorThrown);
          });

Funcionou muito bem. Eu tentei várias maneiras diferentes de fazer isso, mas achei a mais simples e a mais reutilizável. Espero que ajude

Eric Sean Moore
fonte
0

Veja a minha solução:

1.Insira esta função (e variável) no seu arquivo javascript:

var runFunctionQueue_callback;

function runFunctionQueue(f, index, callback) {

  var next_index = index + 1

  if (callback !== undefined) runFunctionQueue_callback = callback;

  if (f[next_index] !== undefined) {
    console.log(index + ' Next function avalaible -> ' + next_index);
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      complete: function() {
        runFunctionQueue(f, next_index);
      }
    });
  } else {
    console.log(index + ' Last function');
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      async: false,
      complete: runFunctionQueue_callback
    });
  }
}

2.Configure uma matriz com seus pedidos, desta forma:

var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];

Função 3.Create callback:

function Function_callback() {
  alert('done');
}

4. Ligue para a função runFunctionQueue com os parâmetros:

runFunctionQueue(f, 0, QuestionInsert_callback);
// first parameter: array with requests data
// second parameter: start from first request
// third parameter: the callback function
Briganti
fonte
-4

Tente assim. faça um loop dentro da função de script java para esperar até que a chamada ajax termine.

function getLabelById(id)
{
    var label = '';
    var done = false;
    $.ajax({
       cache: false,
       url: "YourMvcActionUrl",
       type: "GET",
       dataType: "json",
       async: false,
       error: function (result) {
         label='undefined';
         done = true;
        },
       success: function (result) {
            label = result.Message;
            done = true;
        }
     });

   //A loop to check done if ajax call is done.
   while (!done)
   {
      setTimeout(function(){ },500); // take a sleep.
   }

    return label;
}
ChinaHelloWorld
fonte
1
O seu setTimeout()NÃO take a sleep. Nesse caso, você apenas bloqueia todas as guias até que donese torne realidade.
Alexis Wilke
1
Eu acho que esse é o tópico que pede: "Aguarde até que todas as solicitações do jQuery Ajax sejam concluídas".
ChinaHelloWorld
1
Você já testou esse código? minha expectativa é que donenunca seja verdade enquanto o loop while ainda estiver em execução. Se o loop while estiver em execução, o loop de eventos não poderá continuar e, portanto, nunca executará o retorno de chamada para o sucesso do ajax.
Kevin B