2011-06-30 9 views
47

Mam trzywarstwowy, głęboki łańcuch odroczonych wywołań ajaxowych, i idealnie będą kopać obietnicę aż do zakończenia najgłębszej warstwy (czyni mnie rzeczą początkową. .. "musimy zejść głębiej!").jQuery Odroczona - oczekiwanie na wiele żądań AJAX, aby zakończyć

Problem polega na tym, że wysyłam wiele żądań ajaxowych (być może setek) jednocześnie i muszę odłożyć na później, dopóki wszystkie nie zostaną wykonane. Nie mogę polegać na tym, że ostatnia jest ostatnia.

function updateAllNotes() { 
    return $.Deferred(function(dfd_uan) { 
     getcount = 0; 
     getreturn = 0; 
     for (i = 0; i <= index.data.length - 1; i++) { 
      getcount++; 
      $.when(getNote(index.data[i].key)).done(function() { 
       // getNote is another deferred 
       getreturn++ 
      }); 
     }; 
     // need help here 
     // when getreturn == getcount, dfd_uan.resolve() 
    }).promise(); 
}; 
+1

http://stackoverflow.com/questions/3709597/wait-until -all-jquery-ajax-request-are-done/9350515 # 9350515 – Benjamin

Odpowiedz

95

Można użyć .when() i .apply() z wieloma odroczone. Niezwykle przydatny:

function updateAllNotes() { 
    var getarray = [], 
     i, len; 

    for (i = 0, len = data.length; i < len; i += 1) { 
     getarray.push(getNote(data[i].key)); 
    }; 

    $.when.apply($, getarray).done(function() { 
     // do things that need to wait until ALL gets are done 
    }); 
} 
+8

Możesz także _akceptować własną odpowiedź. W ten sposób możesz pomóc innym, którzy mają podobny problem, ponieważ zobaczą, że problem został rozwiązany w wynikach wyszukiwania. :) – Exa

+0

Dzięki. Oznaczone jako zaakceptowane – brittohalloran

+0

Czy istnieje jakiś powód, aby określić '$' jako pierwszy argument do zastosowania? Rozumiem, że jest to kontekst połączenia, ale czy nie jest to normalny kontekst dla wywołania jQuery 'window' lub nawet' null'? – Ryley

5

Dzięki za odpowiedź brittohalloran. Używam również podkreślenia, więc udało mi się zastosować rozwiązanie bardzo czysto na mapie, trochę tak:

$.when.apply($, _.map(data, function(i) { 
    return getNote(i.key); 
})).done(function() { 
    alert('Be Happy'); 
}); 

Wicked użyteczne.

25

Jeśli odwołasz się do jQuery.When doc, jeśli jedno z twoich wywołań ajax zawiedzie, fail główne wywołanie zwrotne zostanie wywołane, nawet jeśli wszystkie następne wywołania ajax jeszcze się nie zakończyły. W takim przypadku nie masz pewności, że wszystkie połączenia zostały zakończone.

Jeśli chcesz czekać na wszystkich połączeń, bez względu na wynik jest, trzeba użyć innego odroczony tak:

$.when.apply($, $.map(data, function(i) { 
    var dfd = $.Deferred(); 
    // you can add .done and .fail if you want to keep track of each results individualy 
    getNote(i.key).always(function() { dfd.resolve(); }); 
    return dfd.promise(); 
}); 
+0

Nie sądzę, zawsze pomaga w ogóle, ponieważ [nadal działa przed obietnice są spełnione] (http://jsfiddle.net/katowulf/J7H6M/). – Kato

+2

Tak, to pomoże, jeśli użyjesz tego samego kodu co ja i zawiniesz swoje obietnice. [Zaktualizowałem twoje skrzypce] (http://jsfiddle.net/J7H6M/2/) z moim przykładem i działa idealnie. w twoim linku, po prostu zrobiłeś to samo co Brittohalloran, dwie obietnice nie zostały zapakowane. W takim przypadku, jeśli pierwsza się nie powiedzie, wywołania zwrotne fail/always będą wywoływane, nawet jeśli kolejne obietnice nie zostaną zakończone. – Mordhak

Powiązane problemy