2012-03-26 12 views
30

Mam problem z używaniem jQuery.when() do oczekiwania na zakończenie wielu żądań ajaxowych przed wywołaniem innej funkcji.jQuery. Przy rozwiązywaniu problemów ze zmienną liczbą argumentów

Każde żądanie ajax dostanie danych JSON, i wygląda mniej więcej tak:

function loadData(arg){ 
     var ajaxCall = $.ajax(
      URL // depends on arg 
     ) 
     .error(....); 
     return ajaxCall; 
    } 

Jeżeli wniosek jest nazywany, wartość zwracana (ajaxCall) dodaje się do listy o nazwie ajaxRequests.

ajaxRequests = []; 
    ajaxREquests.push(loadData(arg)) 

Gdy wszystkie wnioski zostały dokonane, próbuję przekazać ajaxRequests do $ .Przy aby czekać na wszystkich żądań, aby zakończyć.

 var defer = $.when.apply($, ajaxRequests); 
     defer.done(function(args){ 
      for (var i=0; i<args.length; i++){ 
       inst.loadData($.parseJSON(args[i].responseText)); 
      } 
      inst.draw(); 
     }); 

inst jest obiektem, który ładuje i rysuje wykresy na podstawie danych JSON.

Problem polega na tym, że wygląda na to, że nie oczekuje on na zakończenie żądań - args [i] jest obiektem, ale responseText jest niezdefiniowany, gdy kod zostanie uruchomiony. Jeśli zapiszę argumenty [i] i uzyskam do nich dostęp później z konsoli, to działa.

Podejrzewam, że problem jest związany z używaniem .w przypadku dowolnej liczby argumentów, ponieważ wszystkie przykłady, które widziałem w sieci, zawierają predefiniowaną listę argumentów.

Nie jestem pewien, czy użycie polecenia było właściwe, czy nie, ale tak czy inaczej nie działa poprawnie i zachowuje się nieregularnie (zależnie od przeglądarki).

Każda pomoc zostanie bardzo doceniona.

Proszę dać mi znać, jeśli potrzebujesz więcej informacji.
Używam jQuery 1.5

+1

Może to tylko ja, ale składnia masz w kodzie nie wydaje się zgodny z API jQuery (http: //api.jquery. com/jQuery.when /). Być może chcesz wypróbować tę składnię i zobaczyć, czy to działa? – fayerth

+0

Uważam, że jego punktem było to, że nie używa go tak, jak pokazano w dokumentach, ponieważ ma on zmienną liczbę argumentów. –

+0

@ grennis Dokładnie. – Alex

Odpowiedz

32

Chociaż Alex rzeczywiście rozwiązał ten problem, stwierdziłem, że podążanie nim jest trochę trudne. Miałem problem podobny do tego, który rozwiązałem i chciałem udostępnić moje rozwiązanie każdemu, kto potrzebuje przetworzyć zmienną liczbę żądań ajax.

// Array of requests 
var requests = Array(); 
requests.push($.get('responsePage.php?data=foo')); 
requests.push($.get('responsePage.php?data=bar')); 

var defer = $.when.apply($, requests); 
defer.done(function(){ 

    // This is executed only after every ajax request has been completed 

    $.each(arguments, function(index, responseData){ 
     // "responseData" will contain an array of response information for each specific request 
    }); 

}); 
+0

Dzięki Andy! Pracował dla mnie. – aldux

+0

Dzięki za napisanie Andy :) to jest o wiele jaśniejsze – Alex

+3

dzięki Andy, działa świetnie, o ile wszystkie żądania się powiodły, ale jak sobie z tym poradzisz, jeśli ci się uda, a jeden zawiedzie? –

4

Chyba pracował go teraz - problem był w przetwarzaniu zwróconych argumenty. .done otrzymywało tylko trzy argumenty - tekst odpowiedzi, status i obiekt jqXHR. Spodziewałem się, że zostanie przekazany obiekt jqXHR wynikający z każdego zapytania.

Rozwiązałem to, przesuwając kod wywołania dla każdego zapytania do oddzielnej funkcji (tj. Wywołanie ajax w loadData określa teraz funkcję zwrotną, która wywołuje wywołanie ".loadData (...)" i jedyną rzeczą wykonywaną przez wywołanie .done jest inst.draw(). To wydaje się działać dobrze: indywidualne wywołania zwrotne są wykonywane przed .done().

Nie jestem pewien, czy to jest dokładnie to, jak powinno działać, ale wydaje się, że wykonuje to zadanie.

9

Oprócz odpowiedzi na Andy'ego Corman (jestem jeszcze w stanie odpowiedzieć na post, myślę ...), jeśli masz tylko jedną prośbę, informacje o odpowiedź zostanie przekazana bezpośrednio do odroczyć.done - funkcja jako argument; Więc trzeba zapewnić if w tym przypadku:

// Array of requests 
var requests = Array(); 
requests.push($.get('responsePage.php?data=foo')); 

var defer = $.when.apply($, requests); 
defer.done(function(){ 

    // This is executed only after every ajax request has been completed 
    if (requests.length == 1) 
     // "arguments" will be the array of response information for the request 
    else 
     $.each(arguments, function(index, responseData){ 
      // "responseData" will contain an array of response information for each specific request 
     }); 
}); 
+0

Nie działa dłużej w wersji 1.1.3. Wykonano polecenie Done() po wydaniu wszystkich żądań. –

Powiązane problemy