2013-02-22 10 views
12

Ho tre funzioni che sto cercando di eseguire, le prime due stanno facendo alcune cose asincrone che necessitano di dati per il terzo da utilizzare. Voglio che la terza funzione venga attivata solo quando 1 e 2 sono entrambi eseguiti. questa è la struttura generale ma la funzione finale sta sparando prima della 1 e 2 fine.jquery funzioni differite personalizzate

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 
    } 

} 

risposta è stata di non chiamare la costruzione di dati immediatamente

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

risposta

23

È necessario restituire l'oggetto promessa. Hai anche un errore in questa linea:

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

Va

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

Quindi tutti insieme potrebbe essere:

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

non chiamare i dati di costruzione ha fatto immediatamente il trucco grazie! – Brian

+0

wow, non sapevo che la funzione possa essere scritta all'interno dell'oggetto posticipato in questo modo, grazie! – Denis

+0

@Denis Non penso che sia il modo corretto di farlo. Secondo jQuery [docs] (https://api.jquery.com/jquery.deferred/): Il parametro 'beforeStart' è _" una funzione chiamata appena prima che il costruttore ritorni. "_. Quindi quella funzione viene chiamata prima che venga creato l'oggetto posticipato. –

1

penso che si dovrebbe avere first() e second() restituire una promessa: return d.promise();. Dal docs:

Se un singolo argomento viene passato alla jQuery.when e non è un differite o una promessa, sarà trattato come un risolti differita e gli eventuali allegati doneCallbacks verrà eseguita immediatamente.

ho il sospetto che questo potrebbe essere il motivo per cui la chiamata when sta chiamando constructData troppo presto.

È difficile distinguere il codice, ma accertarsi di chiamare lo d.resolve() al termine delle operazioni asincrone.

Potresti scoprire che un approccio più naturale all'impostazione esplicita di data1 e data2 è invece di utilizzare i dati forniti quando viene chiamato resolve. Ciò significherebbe che la chiamata when sarebbe simile a questa:

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

    constructData(); 
}); 

Nota che il formato esatto di risultati forniti al metodo done dipende dalla natura degli oggetti differite. Se le promesse vengono restituite da una chiamata a $.ajax, i risultati dovrebbero essere del modulo [data, statusText, jqXhrObject].

+0

Sì non ho aggiunto tutto il codice asincrono è tutto un mucchio di richieste personalizzate di jjery non jquery, errore era come ho chiamato la funzione done – Brian

Problemi correlati