jQuery: restituisci i dati dopo il successo della chiamata ajax

Ho qualcosa del genere, in cui è una semplice chiamata a uno script che mi restituisce un valore, una stringa ..

function testAjax() { $.ajax({ url: "getvalue.php", success: function(data) { return data; } }); } 

ma se chiamo qualcosa del genere

 var output = testAjax(svar); // output will be undefined... 

quindi, come posso restituire il valore? il codice qui sotto non sembra funzionare neanche …

 function testAjax() { $.ajax({ url: "getvalue.php", success: function(data) { } }); return data; } 

L’unico modo per restituire i dati dalla funzione sarebbe quello di effettuare una chiamata sincrona anziché una chiamata asincrona, ma che congelerebbe il browser mentre è in attesa della risposta.

È ansible passare una funzione di callback che gestisce il risultato:

 function testAjax(handleData) { $.ajax({ url:"getvalue.php", success:function(data) { handleData(data); } }); } 

Chiamalo così:

 testAjax(function(output){ // here you use the output }); // Note: the call won't wait for the result, // so it will continue with the code here while waiting. 

Nota: questa risposta è stata scritta nel febbraio 2010.
Vedi gli aggiornamenti dal 2015, 2016 e 2017 in basso.

Non è ansible restituire nulla da una funzione che è asincrona. Quello che puoi restituire è una promise . Ho spiegato come le promesse funzionano in jQuery nelle mie risposte a quelle domande:

  • Funzione JavaScript che restituisce i dati delle chiamate AJAX
  • jQuery jqXHR – cancella le chiamate concatenate, triggers la catena degli errori

Se potessi spiegare perché vuoi restituire i dati e cosa vuoi fare in seguito, allora potrei essere in grado di darti una risposta più specifica su come farlo.

Generalmente, invece di:

 function testAjax() { $.ajax({ url: "getvalue.php", success: function(data) { return data; } }); } 

puoi scrivere la tua funzione testAjax in questo modo:

 function testAjax() { return $.ajax({ url: "getvalue.php" }); } 

Quindi puoi ottenere la tua promise in questo modo:

 var promise = testAjax(); 

Puoi memorizzare la tua promise, puoi passarla in giro, puoi usarlo come argomento nelle chiamate alle funzioni e puoi restituirlo dalle funzioni, ma quando finalmente vuoi usare i tuoi dati che vengono restituiti dalla chiamata AJAX, devi Fai cosi:

 promise.success(function (data) { alert(data); }); 

(Vedi gli aggiornamenti di seguito per la syntax semplificata.)

Se i tuoi dati sono disponibili a questo punto, questa funzione verrà richiamata immediatamente. Se non lo è, verrà richiamato non appena i dati saranno disponibili.

Il punto di tutto questo è che i tuoi dati non sono disponibili immediatamente dopo la chiamata a $ .ajax perché è asincrono. Promises è una bella astrazione per le funzioni da dire: non posso restituirti i dati perché non ce l’ho ancora e non voglio bloccare e farti aspettare, ecco invece una promise e sarai in grado di usalo più tardi, o semplicemente darlo a qualcun altro e farlo con esso.

Guarda questa DEMO .

AGGIORNAMENTO (2015)

Attualmente (da marzo 2015) jQuery Promises non sono compatibili con le specifiche Promises / A +, il che significa che potrebbero non cooperare molto bene con altre implementazioni promesse / A + conformi .

Tuttavia, jQuery Promises nella prossima versione 3.x sarà compatibile con le specifiche Promises / A + (grazie a Benjamin Gruenbaum per averlo indicato). Attualmente (a partire da maggio 2015) le versioni stabili di jQuery sono 1.xe 2.x.

Quello che ho spiegato sopra (nel marzo 2011) è un modo per usare jQuery Deferred Objects per fare qualcosa in modo asincrono che nel codice sincrono sarebbe ottenuto restituendo un valore.

Ma una chiamata di funzione sincrona può fare due cose: può restituire un valore (se può) o lanciare un’eccezione (se non può restituire un valore). Promises / A + affronta entrambi questi casi d’uso in modo abbastanza potente come la gestione delle eccezioni nel codice sincrono. La versione jQuery gestisce l’equivalente di restituire un valore, ma l’equivalente di una gestione delle eccezioni complessa è in qualche modo problematico.

In particolare, l’intero punto di gestione delle eccezioni nel codice sincrono non si limita a rinunciare a un bel messaggio, ma cerca di risolvere il problema e di continuare l’esecuzione, o eventualmente di rilanciare la stessa o un’altra eccezione per alcune altre parti del programma maniglia. Nel codice sincrono hai uno stack di chiamate. Nella chiamata asincrona non si esegue una gestione avanzata delle eccezioni all’interno delle proprie promesse, come richiesto dalle specifiche Promises / A +, in realtà può aiutare a scrivere codice che gestirà errori ed eccezioni in modo significativo anche per casi d’uso complessi.

Per le differenze tra jQuery e altre implementazioni e come convertire le promesse di jQuery in Promises / A + compliant, vedi Coming from jQuery di Kris Kowal et al. sulla libreria Q wiki e Promises arrivano in JavaScript da Jake Archibald su HTML5 Rocks.

Come restituire una vera promise

La funzione del mio esempio sopra:

 function testAjax() { return $.ajax({ url: "getvalue.php" }); } 

restituisce un object jqXHR, che è un object rinviato jQuery.

Per fare in modo che ritorni una vera promise, puoi cambiarlo con il metodo del wiki Q :

 function testAjax() { return Q($.ajax({ url: "getvalue.php" })); } 

oppure, usando il metodo dall’articolo HTML5 Rocks :

 function testAjax() { return Promise.resolve($.ajax({ url: "getvalue.php" })); } 

Questo Promise.resolve($.ajax(...)) è anche ciò che è spiegato nella documentazione del modulo di promise e dovrebbe funzionare con ES6 Promise.resolve() .

Per utilizzare le promesse ES6 oggi è ansible utilizzare il polyfill() di es6-promise module di Jake Archibald.

Per vedere dove è ansible utilizzare le promesse ES6 senza polyfill, vedere: Posso usare: Promises .

Per maggiori informazioni vedi:

Futuro di jQuery

Le versioni future di jQuery (a partire da 3.x – le versioni stabili correnti a partire da maggio 2015 sono 1.xe 2.x) saranno compatibili con le specifiche Promises / A + (grazie a Benjamin Gruenbaum per averlo indicato nei commenti). “Due modifiche che abbiamo già deciso sono la compatibilità Promise / A + per la nostra implementazione rinviata […]” ( jQuery 3.0 e il futuro dello sviluppo Web ). Per maggiori informazioni consultare: jQuery 3.0: The Next Generations di Dave Methvin e jQuery 3.0: Maggiore interoperabilità, meno Internet Explorer di Paul Krill.

Colloqui interessanti

  • Boom, Promises / A + è nato da Domenic Denicola (JSConfUS 2013)
  • Redemption from Callback Hell di Michael Jackson e Domenic Denicola (HTML5DevConf 2013)
  • JavaScript Promises di David M. Lee (Nodevember 2014)

AGGIORNAMENTO (2016)

C’è una nuova syntax in ECMA-262, 6a Edizione, Sezione 14.2 chiamate funzioni freccia che possono essere utilizzate per semplificare ulteriormente gli esempi sopra.

Utilizzando l’API jQuery, anziché:

 promise.success(function (data) { alert(data); }); 

tu puoi scrivere:

 promise.success(data => alert(data)); 

o usando l’API Promises / A +:

 promise.then(data => alert(data)); 

Ricorda di usare sempre i gestori di rifiuto con:

 promise.then(data => alert(data), error => alert(error)); 

o con:

 promise.then(data => alert(data)).catch(error => alert(error)); 

Guarda questa risposta per capire perché dovresti usare sempre i gestori di rifiuto con le promesse:

  • Dovrei astenermi dal gestire il rifiuto di Promise in modo asincrono?

Ovviamente in questo esempio potresti usare solo promise.then(alert) perché stai chiamando alert con gli stessi argomenti del tuo callback, ma la syntax della freccia è più generale e ti permette di scrivere cose come:

 promise.then(data => alert("x is " + data.x)); 

Non tutti i browser supportano ancora questa syntax, ma ci sono alcuni casi in cui sei sicuro di quale browser verrà eseguito il tuo codice – ad esempio quando scrivi un’estensione di Chrome , un componente aggiuntivo di Firefox o un’applicazione desktop che utilizza Electron, NW.js o AppJS (vedi questa risposta per i dettagli).

Per il supporto delle funzioni freccia, vedere:

AGGIORNAMENTO (2017)

C’è una syntax ancora più recente che ora si chiama funzioni asincrone con una nuova parola chiave await che al posto di questo codice:

 functionReturningPromise() .then(data => console.log('Data:', data)) .catch(error => console.log('Error:', error)); 

ti lascia scrivere:

 try { let data = await functionReturningPromise(); console.log('Data:', data); } catch (error) { console.log('Error:', error); } 

Puoi usarlo solo all’interno di una funzione creata con la parola chiave async . Per maggiori informazioni, vedi:

Per il supporto nei browser, vedere:

Per supporto nel nodo, vedere:

Nei luoghi in cui non hai il supporto nativo per async e await puoi usare Babel:

o con una syntax leggermente diversa un approccio basato sul generatore come nelle coroutine di co o bluebird:

Ulteriori informazioni

Altre domande sulle promesse per maggiori dettagli:

  • promise chiamata separata dalla promise di risoluzione
  • Q Ritardo promise
  • Return Promise result invece di Promise
  • Esportazione del modulo dal risultato della promise
  • Cosa c’è di sbagliato nella risoluzione delle promesse?
  • Restituisce il valore in funzione da un blocco promise
  • Come posso restituire lo stato all’interno della promise?
  • Dovrei astenermi dal gestire il rifiuto di Promise in modo asincrono?
  • Il concetto di differita / promise in JavaScript è nuovo o è una parte tradizionale della programmazione funzionale?
  • Come posso concatenare queste funzioni con le promesse?
  • Promise.all in JavaScript: come ottenere valore risolutivo per tutte le promesse?
  • Perché Promise.all non è definito
  • la funzione restituirà null da javascript post / get
  • Usa cancel () all’interno di una catena a catena creata da promisifyAll
  • Perché è ansible passare un parametro non funzionale a Promise.then () senza causare un errore?
  • Implementa un modello di promesse
  • Promesse e prestazioni
  • Difficoltà a raschiare due URL con promesse
  • http.request non restituisce dati anche dopo aver specificato il ritorno sull’evento ‘end’
  • async.each non iterando quando si usano le promesse
  • jQuery jqXHR – cancella le chiamate concatenate, triggers la catena degli errori
  • Modo corretto di gestire le promesse e la risposta del server
  • Restituisce un valore da una chiamata di funzione prima di completare tutte le operazioni all’interno della funzione stessa?
  • Risoluzione di un setTimeout all’interno dell’endpoint API
  • Async aspetta una funzione
  • Funzione JavaScript che restituisce i dati delle chiamate AJAX
  • prova / cattura i blocchi con async / await
  • jQuery Deferred non chiama le richiamate risoluzione / risposta in ordine
  • Il ritorno dei dati da ajax provoca strani oggetti
  • javascript – Perché esiste una specifica per i moduli di sincronizzazione e asincrona?

è ansible aggiungere l’opzione asincrona a false e tornare all’esterno della chiamata ajax.

 function testAjax() { var result=""; $.ajax({ url:"getvalue.php", async: false, success:function(data) { result = data; } }); return result; } 

Idk se voi ragazzi lo avete risolto ma vi consiglio un altro modo per farlo, e funziona 🙂

  ServiceUtil = ig.Class.extend({ base_url : 'someurl', sendRequest: function(request) { var url = this.base_url + request; var requestVar = new XMLHttpRequest(); dataGet = false; $.ajax({ url: url, async: false, type: "get", success: function(data){ ServiceUtil.objDataReturned = data; } }); return ServiceUtil.objDataReturned; } }) 

Quindi l’idea principale qui è che aggiungendo asincrono: falso, quindi fai in modo che tutto rimanga fino a quando i dati non vengono recuperati. Quindi lo assegni a una variabile statica della class e tutto funziona magicamente 🙂

Vedere l’esempio di jquery docs: http://api.jquery.com/jQuery.ajax/ (circa 2/3 della pagina)

Forse stai cercando il seguente codice:

  $.ajax({ url: 'ajax/test.html', success: function(data) { $('.result').html(data); alert('Load was performsd.'); } }); 

Stessa pagina … più in basso.