2013-02-22 13 views
12

Mam trzy funkcje, które próbuję uruchomić, pierwsze dwa robią pewne asynchroniczne rzeczy, które potrzebują danych dla trzeciej osoby. Chcę, aby trzecia funkcja strzelała tylko wtedy, gdy 1 i 2 zostały wykonane. jest to ogólna struktura, ale ostatnia funkcja odpala przed 1 i 2.niestandardowe funkcje odroczone jquery

function run() { 
    var data1 = {}; 
    var data2 = {}; 

    $.when(first(), second()).done(constructData()); 

    function first() { 
     var d = new $.Deferred(); 

     //do a bunch of stuff async 
     data1 = {}; 

     d.resolve(); 
    } 
    function second() { 


     var d = new $.Deferred(); 

     //do a bunch of stuff async 
     data2 = {}; 
     d.resolve(); 
    } 
    function constructData() { 
     //do stuff with data1 and data2 
    } 

} 

odpowiedzi nie było nazwać skonstruować dane natychmiast

$.when(first(), second()).done(constructData); 

Odpowiedz

23

Powinieneś zwrócić obiekt obietnicy. Masz również błąd w tej linii:

$.when(first(), second()).done(constructData()); 

powinno być

$.when(first(), second()).done(constructData); // don't call constructData immediately 

Więc wszystko razem może to być:

function run() { 
    var data1 = {}; 
    var data2 = {}; 

    $.when(first(), second()).done(constructData); 

    function first() { 
     return $.Deferred(function() { // <-- see returning Deferred object 
      var self = this; 

      setTimeout(function() { // <-- example of some async operation 
       data1 = {func: 'first', data: true}; 
       self.resolve();  // <-- call resolve method once async is done 
      }, 2000); 
     }); 
    } 
    function second() { 
     return $.Deferred(function() { 
      var self = this; 
      setTimeout(function() { 
       data2 = {func: 'second', data: true}; 
       self.resolve(); 
      }, 3000); 
     }); 
    } 
    function constructData() { 
     //do stuff with data1 and data2 
     console.log(data1, data2); 
    } 
} 

http://jsfiddle.net/FwXZC/

+0

nie wywoływanie danych konstrukcyjnych natychmiast wykonało lewę dzięki! – Brian

+0

Wow, nie wiedziałem, że funkcja ta może być zapisana wewnątrz obiektu odroczonego w ten sposób, dzięki! – Denis

+0

@Denis Nie sądzę, że to właściwy sposób robienia tego. Zgodnie z jQuery [docs] (https://api.jquery.com/jquery.deferred/): Parametrem 'beforeStart' jest _" funkcja, która jest wywoływana tuż przed powrotem konstruktora. "_. Funkcja ta jest wywoływana przed utworzeniem obiektu odroczonego. –

1

myślę, że należy mieć first() i second() powrócić obietnicę: return d.promise();. Od docs:

Jeśli pojedynczy argument przekazany do jQuery.when i to nie jest odroczony lub obietnica, będzie ona traktowana jako rozwiązany odroczony oraz wszelkie doneCallbacks dołączone będą wykonywane natychmiast.

Podejrzewam, że to może być powód, dla którego wywołanie when wywołuje zbyt szybko wywołanie constructData.

Ciężko powiedzieć z twojego kodu, ale upewnij się, że dzwonisz pod numer d.resolve() po zakończeniu operacji asynchronicznych.

Może się okazać, że bardziej naturalnym podejściem do jawnego ustawienia data1 i data2 jest użycie danych dostarczonych po wywołaniu resolve. Oznaczałoby to, że rozmowa when będzie wyglądać mniej więcej tak:

$.when(first(), second()).done(function(result1, result2) { 
    data1 = result1[0]; 
    data2 = result2[0]; 

    constructData(); 
}); 

Należy zauważyć, że dokładny format wyników dostarczonych do metody done zależy od charakteru odroczonego obiektów. Jeśli obietnice zostaną zwrócone z połączenia pod numer $.ajax, wyniki powinny być w postaci [data, statusText, jqXhrObject].

+0

Tak Nie dodałem cały kod asynchroniczny to cała masa niestandardowych zapytań ajaxowych, nie jest tak jak nazwałem wykonaną funkcję – Brian

Powiązane problemy