2012-06-10 4 views
15

Ho riscontrato un problema con la funzione $ .get. L'URL contiene JSONRendi la funzione "get" AJAX sincrona/come ottenere il risultato?

il mio codice:

xyz = null 

    $.get('http://www.someurl.com/123=json', function(data) { 
     var xyz = data.positions[0].latitude; 
    }); 

alert(xyz); 
//some more code using xyz variable 

So che xyz avviserà un risultato nullo perché l'$.get è asincrono.

Quindi è possibile utilizzare lo xyz all'esterno di questa funzione?

+0

Se muovi la parola chiave 'var' dal tuo funzione e davanti al tuo 'xyz' iniziale, quindi puoi usarlo ovunque in quell'ambito in qualsiasi funzione che viene eseguita dopo il completamento della richiesta ajax. – Paulpro

+4

Anche se * è * ** sincrono ** AJAX (è * documentato * in jQuery), di solito dovrebbe * essere evitato * a causa dell'impatto negativo che ha sull'esperienza utente. Concentrati invece sull'utilizzo del modello basato su eventi di AJAX asincrono. Ovvero, aggiorna il DOM con 'xyz' * da * il callback. –

+0

@pst. La stessa domanda tutto il tempo. Questo e il problema del DOM pronto. – gdoron

risposta

7

la vera risposta è NO , ma è possibile utilizzare questo:

function useXYZ(){ 
    alert(xyz); 
} 

xyz = null   

$.get('http://www.someurl.com/123=json', function(data) { 
    xyz = data.positions[0].latitude; 
    useXYZ(); 
}); 
+0

Perché sprecare tempo e confusione mentale in una proprietà globale? (O variabile chiusa). Spesso è meglio scrivere come 'function useXYZ (xyz) {..}' ... e poi passare attraverso i dati dal callback. –

+0

@pst. Ho pensato di farlo, ma volevo mostrargli come usare la variabile esterna. (A proposito, non deve essere una variabile globale). Puoi modificare come desideri signore! – gdoron

+0

Grazie! Ho pensato che funzionasse bene con l'avviso che ho ancora problemi con il resto della sceneggiatura. E in effetti quando devo mettere un sacco di roba nella funzione useXYZ() {...} – Diolor

22

get è una scorciatoia. Si può fare lo stesso, ma sincrono, utilizzando:

var xyz = null 


$.ajax({ url: 'http://www.someurl.com/123=json', 
     async: false, 
     dataType: 'json', 
     success: function(data) { 
       xyz = data.positions[0].latitude; 
      } 
     }); 


alert(xyz); 

Dovrai dichiarare la variabile xyz prima della chiamata ajax, però.

+0

Beh, in tutta onestà la mia risposta iniziale era scarsa. Dovrei davvero smettere di provare a rispondere alle domande dal mio telefono. – HackedByChinese

+0

In Chrome e Firefox sto ancora ottenendo un null. In safari funziona bene – Diolor

+0

Hmm. Ho provato con Safari, Chrome e Firefox (su OSX). Ecco un esempio puro http://jsfiddle.net/HackedByChinese/F2Ey5/1/ – HackedByChinese

4

Questo è un problema comune con Javascript. Il codice Javascript deve essere scritto in stile passaggio continuo. È fastidioso ma è qualcosa che puoi convertire senza pensare troppo.

Basicaly, ogni volta che avremmo qualcosa come

var x = someSyncFunction(a, b, c); 
//do something with x 
console.log(x); 

possiamo convertirlo in codice asincrono per rendere tutto il codice dopo la funzione restituisce in una funzione continuazione e girando x da una variabile in un parametro del callback di continuazione.

someAsyncFunction(a, b, c, function(x){ 
    //do something with x; 
    console.log(x); 
}); 

Devi fare attenzione che è molto facile scrivere codice confuso. Un buon trucco da tenere a mente è che puoi far sì che le tue funzioni ricevano anche i callback. Questo permette loro di essere utilizzati da diverse funzioni (proprio come le normali funzioni di sincronizzazione di supporto che restituisce un valore può essere utilizzato da diverse funzioni)

var getXyz = function(onResult){ //async functions that return do so via callbacks 
           //you can also another callback for errors (kind of analogous to throw) 
    $.get('http://www.someurl.com/123=json', function(data) { 
     var xyz = data.positions[0].latitude; 
     onResult(xyz); //instead of writing "return xyz", we pass x to the callback explicitely. 
    }); 
}; 

getXyz(function(xyz){ //this would look like "var xyz = getXyz();" if it were sync code instead. 
    console.log('got xyz'); 
}); 

Il trucco è quello di cambiare tutte le dichiarazioni di ritorno dalla funzione in chiamate al funzione di callback. Pensa come se la funzione asincrona non fosse mai ritornata e l'unico modo per restituire un valore a qualcuno è di passare quel valore a un callback.


Si potrebbe chiedere perché non c'è un modo più semplice per fare tutto questo. Beh, non c'è, a meno che non usi un'altra lingua invece di Javascript (o almeno qualcosa che ti permetta di scrivere codice asincrono in stile sincrono ma compili automaticamente in Javascript)

+0

Grazie! E se dovessi prendere due vars da JSON come "xyz" per la latitudine e "abc" per la longitudine? Come sarebbe il onResult e la funzione (xyz). Potrei annidarli entrambi al suo interno o dovrei creare una seconda funzione (abc)? – Diolor

+0

È possibile comprimere entrambi i valori all'interno di un singolo oggetto e passare l'oggetto al callback 'onResult ({lat: xyz, long: abc});', analogamente a come si restituirebbero più valori da una funzione sincrona) o si potrebbe avere la funzione di callback riceve due parametri invece di uno 'onResult (xyz, abc);'. Avere più di un callback è usuale per percorsi di calcolo diversi e mutuamente esclusivi. Un esempio comune è avere un callback di successo (o "return") e un callback di errore (o "throw"). – hugomg