2012-01-04 12 views
8

Pozwól mi wyjaśnić trochę mój kod (Przepraszam, jeśli coś jest nie tak, właśnie napisałem ten przykład od zera, jest on bardzo zbliżony do tego, co obecnie mam).Wiele wywołań ajaxowych wewnątrz każdej funkcji(). Zrób coś, gdy WSZYSTKIE z nich zostanie zakończone?

HTML:

<form id="form"> 
    <!-- Friend 1 --> 
    Name 1: <input type="text" name="friendName1" id="friendName1" class="friendName" value=""><br /> 
    Email 1: <input type="text" name="friendEmail1" id="friendEmail1" value=""><br /><br /> 
    <!-- Friend 2 --> 
    Name 2:<input type="text" name="friendName2" id="friendName2" class="friendName" value=""><br /> 
    Email 2:<input type="text" name="friendEmail2" id="friendEmail2" value=""><br /><br /> 
    <!-- Friend 3 --> 
    Name 3:<input type="text" name="friendName3" id="friendName3" class="friendName" value=""><br /> 
    Email 3:<input type="text" name="friendEmail3" id="friendEmail3" value=""><br /><br /> 
    <!-- Friend 4 --> 
    Name 4:<input type="text" name="friendName4" id="friendName4" class="friendName" value=""><br /> 
    Email 4:<input type="text" name="friendEmail4" id="friendEmail4" value=""><br /><br /> 
    <!-- Submit --> 
    <input name="submit" type="submit" value="Submit"> 
</form> 

JS:

$("#form").submit(function(){ 

    $(".friendName[value!='']").each(function(){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     if($("#"+idEmail+"[value!='']").length > 0){ 
      var name = $(this).val(); 
      var email = $("#"+idEmail).val(); 

      // Submit the ajax request 
      $.ajax({ 
       type: 'POST', 
       url: 'ajax/url', 
       data: { 
        name: name, 
        email: email 
       }, 
       success: function(json) { 
        // Log a console entry if our ajax request was successful 
        console.log(name + " was submitted via ajax"); 
       } 
      }); 
     } 
    }); 

    // Redirect the user to the thank you page 
    setTimeout(function() { window.location= '/thanks'; }, 2000); 

}); 

JSFiddle (przekierowanie połączenia usunięty i zastąpiony ajax dzienniku konsoli na skrzypcach)

http://jsfiddle.net/cM5PX/

Kod HTML jest prostym formularzem z polami imienia i nazwiska oraz adresu e-mail znajomego.

JS ma każdą funkcję, która jeśli nazwa i powiązany adres e-mail mają wartości, uruchamia wywołanie ajax.

Potrzebuję sposobu na wywołanie tych wywołań ajaxowych (może istnieć 1 pętla, może być 15), a następnie po zakończeniu wszystkich, przekieruj do nowej strony.

Obecny sposób, w jaki to robię, jest okropny, ponieważ wszystkie wywołania ajaxowe nie kończą się przed przekierowaniem strony.

Co mogę zrobić, aby było lepiej? To musi być głupi dowód i TYLKO przekierowanie po zakończeniu wszystkich połączeń ajaxowych (sukces lub błąd, to nie ma znaczenia - wystarczy przekierować po zakończeniu).

Próbowałem użyć async: false, ale nie wydaje się, aby coś zmienić.

Zastanawiałem się nad umieszczeniem licznika w każdej funkcji i liczniku w funkcji sukcesu ajax i jeśli oba pasują do siebie, następnie wykonaj przekierowanie, ale szukam bardziej doświadczonych wskazówek.

Odpowiedz

0

Domyślnie $ .ajax jest asynchroniczne. W haszowaniu opcji, który jest przekazywany, dodaj

Spowoduje to serializację wywołań, które wywołasz, wykonując żądany sposób.


Po otrzymaniu komentarza od oryginalnego plakatu, możliwym rozwiązaniem może być wykonanie następujących czynności:

  • wewnątrz złożyć zadzwonić określić liczbę połączeń, które powinny być wykonane.
  • Store ten wynik jako zmiennej lokalnej w funkcji obsługi
  • Tworzenie zwrotnego na „kompletna:” że zbada wartość połączeń
    • Jeżeli liczba nawiązywanie połączeń jest większa niż 0, następnie zmniejsz wartość i zwróć
    • Jeśli liczba połączeń osiągnie zero, zaktualizuj window.location (naprawdę powinno użyć window.location.href jako okna.Lokalizacja jest przedmiotem ale przeglądarek pozwoli to i wykonać poprawnie)

Uwaga, nie mam żadnych informacji na temat bezpieczeństwa wątku wykonywania tego rodzaju pracy tak YMMV.


Przykład Kod:

$("#form").submit(function(eventObject){ 
    var $ajaxFields= $(".friendName[value!='']").filter(function(index){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     return ($("#"+idEmail+"[value!='']").length > 0); 
    }); 

    var numberToSubmit= $ajaxFields.length; 
    $ajaxFields.each(function(){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     var name = $(this).val(); 
     var email = $("#"+idEmail).val(); 

     // Submit the ajax request 
     $.ajax({ 
      type: 'POST', 
      url: 'ajax/url', 
      data: { 
       name: name, 
       email: email 
      }, 
      success: function(json) { 
       // Log a console entry if our ajax request was successful 
       console.log(name + " was submitted via ajax"); 
      }, 
      error: function(jqXHR, textStatus, errorThrown) { 
       console.log("call not completed: "+textStatus); 
      }, 
      complete: function(jqXHR, textStatus) { 
       if(--numberToSubmit == 0) { 
        window.location.href= '/thanks'; 
       } 
      } 
     }); 
    }); 

    // Prevent default form submission 
    return false; 
}); 
+1

I zablokuje interfejs użytkownika. –

+0

Po prostu zaktualizowałem moje pytanie, próbowałem użyć async: false, ale nie wydaje się, aby to miało znaczenie i nie chcę, aby przeglądarka zawiesiła się podczas wykonywania połączeń. – Latox

+0

Ach ok ... pozwól mi trochę zagłębić. –

2

Wystarczy zachować licznik wywołań AJAX i sprawdzić, kiedy wszystkie one zakończone. coś takiego:

$("#form").submit(function(){ 
    var ajaxMax = $(".friendName[value!='']").length, ajaxCounter = 0; 
    $(".friendName[value!='']").each(function(){ 
     var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName',''); 
     if($("#"+idEmail+"[value!='']").length > 0){ 
      var name = $(this).val(); 
      var email = $("#"+idEmail).val(); 

      // Submit the ajax request 
      $.ajax({ 
       type: 'POST', 
       url: 'ajax/url', 
       data: { 
        name: name, 
        email: email 
       }, 
       success: function(json) { 
        // Log a console entry if our ajax request was successful 
        console.log(name + " was submitted via ajax"); 
        if(++ajaxCounter >= ajaxMax) 
         window.location= '/thanks'; 
       } 
      }); 
     } 
    }); 
}); 
+0

Po prostu zdałem sobie sprawę, że napisany przeze mnie kod nie będzie działał dokładnie, ponieważ masz instrukcję "jeśli", więc będziesz musiał to sprawdzić, obliczając "maksimum". –

27

Zastosowanie deferred objects:

$("#form").submit(function(e){ 

    e.preventDefault(); 

    var calls = []; 

    $(".friendName[value!='']").each(function(){ 
     // Submit the ajax request 
     calls.push($.ajax({ 
      type: 'POST', 
      url: 'ajax/url', 
      data: { 
       name: name, 
       email: email 
      }, 
      success: function(json) { 
       // Log a console entry if our ajax request was successful 
       console.log(name + " was submitted via ajax"); 
      } 
     })); 
    }); 

    $.when.apply($, calls).then(function() { 
     window.location= '/thanks'; 
    }); 
}); 
+0

Brzmi to elegancko, zrobię to i dam ci znać, jak idę. – Latox

+0

To jest niesamowite, nic dziwnego, że masz 157k! ;) Świetna odpowiedź! –

6

Ok, to jest dość łatwe, ponieważ używasz jQuery. jQuery jest wyposażony w zintegrowany procesor obietnic, który jest również połączony z połączeniami Ajax jQuery. Co to znaczy? Cóż, możemy łatwo przejść tak:

var requests = [ ]; 

// ... 

// Submit the ajax request 
requests.push($.ajax({ 
    type: 'POST', 
    url: 'ajax/url', 
    data: { 
     name: name, 
     email: email 
    }, 
    success: function(json) { 
     // Log a console entry if our ajax request was successful 
     console.log(name + " was submitted via ajax"); 
    } 
})); 

// at this point we filled our array with jXHR objects which also inherit the promise API 

$.when.apply(null, requests).done(function() { 
    document.location.href = '/thanks'; 
}); 

Uwaga: Powyższy kod będzie tylko ogień, jeśli wszystkie żądania zakończone powodzeniem. Jeśli zajdzie potrzeba obsłużenia sprawy, jeśli jedno lub więcej żądanych nie powiodło się, użyj .then() lub .fail() zamiast .done().

+0

Felix pobił cię do tego! :(+1 chociaż. – Latox

+1

Rzeczywiście, zrobiłem zbyt wiele "blabla": p – jAndy

+1

SO jest trudnym miejscem;) –