Come posso sfruttare le funzioni di callback per XMLHttpRequest asincrona?

Attualmente sto scrivendo JavaScript e confuso sulla callback . Ho trovato che non è una specie di funzioni built-in però …
Ora sto leggendo la quinta edizione di O’Relly JavaScript e mostra un codice di esempio simile al seguente:

getText = function(url, callback) // How can I use this callback? { var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState == 4 && request.status == 200) { callback(request.responseText); // Another callback here } } request.open('GET', url); request.send(); } 

Fondamentalmente, suppongo che io non capisco l’idea generale di callback però … Qualcuno potrebbe scrivere un codice di esempio per trarre vantaggio dalla callback sopra?

I callback sono abbastanza semplici e ingegnosi! A causa della natura delle chiamate AJAX, non si blocca l’esecuzione del proprio script fino a quando la richiesta non è terminata (sarebbe allora sincrono). Un callback è semplicemente un metodo designato per gestire la risposta una volta che ritorna al tuo metodo.

Poiché i metodi javascript sono oggetti di prima class, puoi passarli come variabili.

Quindi nel tuo esempio

 getText = function(url, callback) // How can I use this callback? { var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState == 4 && request.status == 200) { callback(request.responseText); // Another callback here } }; request.open('GET', url); request.send(); } function mycallback(data) { alert(data); } getText('somephpfile.php', mycallback); //passing mycallback as a method 

Se si fa quanto sopra, significa che si passa mycallback come metodo che gestisce la risposta (callback).

MODIFICARE

Mentre l’esempio qui non illustra il beneficio appropriato di un callback (si potrebbe semplicemente mettere l’avviso nella funzione onReadyStateChange dopo tutto!), L’usabilità è certamente un fattore.

Devi tenere a mente che la cosa importante qui è che i metodi JS sono oggetti di prima class. Ciò significa che puoi passarli intorno come oggetti e collegarli a tutti i tipi di eventi. Quando si triggersno gli eventi, vengono chiamati i metodi associati a tali eventi.

Quando fai request.onreadystatechange = function(){} stai solo assegnando il metodo da chiamare quando scatta l’evento appropriato.

Quindi la cosa interessante qui è che questi metodi possono essere riutilizzati. Supponiamo che tu abbia un metodo di gestione degli errori che compaia un avviso e compili alcuni campi nella pagina HTML nel caso di un 404 nella richiesta AJAX.

Se non è ansible assegnare callback o passare metodi come parametri, si dovrà scrivere il codice di gestione degli errori più e più volte, ma tutto ciò che si deve fare è semplicemente assegnarlo come callback e tutta la gestione degli errori verrà ordinata in un colpo solo.


Prima di tutto suggerirei di leggere su cosa sia una callback. Ecco un inizio.

La grande immagine

Le callback sono ampiamente utilizzate nella programmazione asincrona. Quando non si desidera bloccare fino al completamento di un’operazione (possibilmente) di lunga durata, uno dei modi per affrontare il problema è debind l’operazione a qualcuno che lo farà per conto proprio. Ciò solleva la domanda: come sarai in grado di dire quando l’operazione è completa e come otterrai i suoi risultati?

Una soluzione sarebbe quella di debind il lavoro a qualcun altro e prendere un momento dal tuo lavoro normale di tanto in tanto per chiedere “è il lavoro che ti ho dato fatto ancora?”. Se è così, ottieni i risultati in qualche modo e vai via. Problema risolto.

Il problema con questo approccio è che non ti rende la vita molto più facile. Ora sei costretto a chiedere ogni momento e non saprai che l’operazione è eseguita non appena è effettivamente (ma solo la prossima volta che ti ricordi di chiedere). Se ti dimentichi di chiedere, non sarai mai informato.

Una soluzione migliore è la richiamata: quando si delegano i lavori, si fornisce una funzione. Il codice che farà effettivamente il lavoro promette quindi di chiamare tale funzione non appena il lavoro sarà completato. Ora puoi dimenticare tutto su quella roba ed essere sicuro con la consapevolezza che quando il lavoro sarà terminato, verrà richiamata la tua chiamata. Non prima, e non più tardi.

Qual è la richiamata qui?

In questo caso specifico, callback è una funzione che tu fornisci a getText come modo per permetterti di comunicare con te. In effetti stai dicendo “fai questo lavoro per me, e quando hai finito, ecco una funzione che puoi chiamare per farmi sapere”.

getText sceglie infatti di utilizzare questa callback solo quando il XMLHttpRequest (XHR) è completato, e allo stesso tempo “ti fa sapere” che ti passa anche il contenuto della risposta HTTP (così puoi agire su quelle informazioni).

Richiami e più richiami, oh mio!

Ma prenditi un altro momento per leggere il codice. Qual è il valore che memorizza per request.onreadystatechange ? Qual è lo scopo di request.onreadystatechange ?

La risposta è che request.onreadystatechange è lì per popolare con un callback . In effetti, XHR ti offre un modo per fornirgli un callback e promette di “richiamarti” ogni volta che cambia lo stato della richiesta HTTP sottostante.

getText è una funzione che costruisce un’astrazione in più : si collega al proprio callback (una funzione anonima – mi riferirò a questo come “inner” ) e accetta un altro callback da te (il parametro – I ‘ Lo chiamerò “esterno” ). Quando il callback interno (che, ricorda: viene chiamato ogni volta che lo stato cambia) rileva che lo stato è “completato” (il significato del valore 4 ) e il codice di stato di risposta HTTP è 200 (che significa “OK”), chiama il callback esterno per consentire a te, utente di getText , di conoscere il risultato.

Spero di avere un senso. 🙂

Personalmente preferisco usare Listener di eventi sui callback.

L’uso di Listener è utile soprattutto quando sei disposto a elaborare più richieste asincrone contemporaneamente.

L’utilizzo è il seguente (tratto da https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest )

 function reqListener () { console.log(this.responseText); } var oReq = new XMLHttpRequest(); oReq.addEventListener("load", reqListener); oReq.open("GET", "http://www.example.org/example.txt"); oReq.send() 

Ciò che funziona in un modo appropriato di “callback” è definire un servizio che restituisca una promise come questa!

 $http.head("url2check").then(function () { return true; }, function () { return false; }); 

Nel controller utilizzare il servizio:

 ..then(function (found)) { if (found) {...... } 

@jon è corretto chiamarlo asincrono!