2012-07-12 5 views
14

Come posso utilizzare correttamente jQuery differite per ritardare il ritorno della funzione finché chiamata asincrona entro la funzione completa + ottenere il valore di ritorno?jQuery differito: utilizzare per ritardare il ritorno della funzione fino alla chiamata asincrona entro la funzione completa + ottenere il valore di ritorno

Questo è il mio codice corrente:

function getFields(page) 
{ 
    var dff = $.Deferred(); 
    result = {}; 
    $.ajax(//the async call 
    { 
     url: page, 
     success: 
     function (data) 
     { 
      //work out values for field1 & field 2 from data here 
      result = 
      { 
      'field1' : field1, 
      'field2' : field2 
      }; 
     }, 
     complete: 
     function() 
     { 
      dff.resolve(result); //my attempt to return the result 
     } 
    } 
); 
    return dff.promise(); 
} 

Voglio che questo per stampare { "field1": "value1", "field2": "valore2"}

var result = getFields('http://something'); 
console.log(JSON.stringify(result)); 

Tuttavia, il valore di risultato sembra essere un oggetto jQuery - quindi sto facendo qualcosa di sbagliato, ma cosa?

Grazie!


P.S. Ci scusiamo per la domanda per principianti, sono un utente per la prima volta in differita, quindi sto ancora cogliendo i concetti di base.

risposta

12

L'unico modo per ritardare il ritorno della funzione getFields sarebbe quella di impostare la proprietà AJAX async su false:

var ajaxPromise = $.ajax(
    { 
     url: page, 
     async: false // make the call synchronous 
    } 
); 

Ma la documentazione jQuery nota che questo è deprecato da 1,8 in poi (cioè il suo uso è scoraggiati).

I differimenti non rendono AJAX sincrono, ma facilitano il lavoro con callback e metodi asincroni.

Da quello che posso dire di che cosa si sta cercando di essa potrebbe funzionare meglio per fare qualcosa di simile:

function getFields(page) 
{ 
    var ajaxPromise = $.ajax(//the async call 
    { 
     url: page 
    } 
); 

    var dff = $.Deferred(); 
    ajaxPromise.then(function(data){ 

    // Possibly access the loaded data in this function. 
    var result = { 
     'field1' : field1, 
     'field2' : field2 
    }; 

    // Notify listeners that the AJAX call completed successfully. 
    dff.resolve(result); 

    }, function(){ 
    // Something went wrong - notify listeners: 
    dff.reject(/* possibly pass information about the error */); 
    }); 

    return dff.promise(); 
} 

quindi utilizzare l'oggetto promessa in questo modo:

var fieldPromise = getFields('http://something'); 
fieldPromise.done(function(result){ 
    console.log(JSON.stringify(result)); 
}); 

Si noti che getFields restituisce immediatamente un oggetto Promise ma è necessario attendere che la promessa venga risolta prima di poter uscire dal risultato.

+0

@ Sly_caridnal: +1 e verifica - ottima spiegazione! – bguiz

+0

Oooh, bello ... Avvolgere 'dff.resolve (data);' in un 'setTimeout' è un modo facile e veloce per simulare una chiamata ajax lenta (poiché quello che sto testando non finisce in modo coerente prima o dopo un seconda chiamata ajax) – Izkata

+0

C'è un modo in realtà: cambia la dichiarazione di ritorno della funzione 'getFields (page)' come 'return dff.promise(). getState() == 'resolved'' Si fermerà fino a quando la risoluzione o il rifiuto non si verificano. Ovviamente puoi solo restituire l'oggetto promessa stesso e controllare lo stato da qualche altra parte. – shuangwhywhy

6

Ecco l'idea di base dei differiti: viene restituito un oggetto e lo si può usare per definire le funzioni che verranno richiamate al ritorno del valore. Così si potrebbe fare qualcosa di simile:

function getFields(page) 
{ 
    return $.ajax(page); 
} 

Poi si può chiamare e specificare una funzione da chiamare quando la chiamata XHR completa:

var jqXHR = getFields("/path/to/call"); 
jqXHR.done(function (data) { alert(JSON.stringify(data); }); 

L'oggetto è chainable, quindi si può solo fare questo :

getFields("/path/to/call") 
    .done(function (data) { alert(JSON.stringify(data); }); 

Nota che l'oggetto restituito da jqXHR $.ajax è un oggetto differite compatibile, in modo da poter leggere la documentazione a http://api.jquery.com/category/deferred-object/.

io non sono sicuro di cosa si intende per il vostro codice di esempio (in quanto in realtà non utilizzare la chiamata Ajax), ma forse volevi dire qualcosa di simile:

function getFields() 
{ 
    var df = $.Deferred(); 
    window.setTimeout(function() { 
     df.resolve({field1: "value1", field2: "value2"}); 
    }, 1000); 
    return df.promise(); 
} 

getFields().done(function (data) { console.log(JSON.stringify(data)); }); 

Questo sarà stampare il valore di un desiderato secondo dopo averlo eseguito.

Problemi correlati