LEZIONE I - Scambiare dati con il AJAX
Nella parte introdutiva al corso abbiamo visto che AJAX non è altro che una tecnica di programmazione che fa uso di di più linguaggi. Per fare in modo che questi linguaggi (nel nostro caso JS e PHP) interagiscano tra loro, ci vuole un metodo di scambio dati.
AJAX essendo un sistema dinamico di interazione, può avvalersi di varie tecniche di comunicazione con il server:
1) il modulo XMLHttpRequest
2) un iframe nascosto
Entrambi i metodi sono validi ma hanno dei pregi e dei difetti. Sta a noi poi vedere quale fa più al caso nostro. Diciamo che molte volte un programma utilizza entrambi i metodi in base a quello che dobbiamo fare, e noi vedremo entrambi i metodi utilizzati.
Prima però di procedere al dettaglio sull'uso dei 2 metodi suddetti, vediamo a grandi linee quali sono i pregi e i difetti:
Modulo XMLHttpRequest
E' una funzione intrinseca di tutti gli interpreti JS di ultima generazione.
I suoi pregi sono:
1) viene invocato direttamente dal nostro script JS
2) supporta sia il metodo di invio POST che GET
3) può ricevere i dati sia in formato XML che in semplice testo
4) lavora in modalità asincrona
5) converte automaticamente l'XML in oggetti JS utilizzabili
6) sappiamo quando arriva la risposta del server
7) gestisce gli errori di comunicazione con il server
I suoi difetti:
1) non permette la navigazione delle pagine con i tasti "avanti" e "indietro" del browser
2) non permette l'invio di file con un form enctype='multipart/form-data'
iframe nascosto
E' un elemento HTML standard supportato da tutti i browser.
I suoi pregi sono:
1) permette la navigazione delle pagine con i tasti "avanti" e "indietro" del browser
2) permette l'invio di file con un form enctype='multipart/form-data'
I suoi difetti:
1) non viene invocato direttamente dal nostro script JS
2) non supporta (direttamente) il metodo di invio POST
3) riceve dati solo in formato testo
4) lavora in modalità sincrona
5) non converte l'XML in oggetti JS
6) non sappiamo quando arriva la risposta del server
7) non gestisce gli errori di comunicazione con il server
Come visto sopra, i pregi di un metodo sono i difetti dell'altro metodo; per questo vedremo l'utilizzo di entrambi i metodi di comunicazione ove sarà necessario, anche se ci indirizzeremo maggiormente all'uso di
XMLHttpRequest.
Uso di XMLHttpRequest
L'utilizzo di questo modulo è lungo da spiegare ma è molto semplice da realizare; prevede una URL di richiesta al server e gestisce la risposta di quest'ultimo.
Non c'è moltissimo da dire, il codice va letto così com'è (a parte le variazioni che potete fare alle condizioni) e utilizzato come scritto:
// Verifica se si può utilizzare il modulo XMLHttpRequest
if ( window.XMLHttpRequest ) {
httpRequest = new XMLHttpRequest();
// Verifica se, mancando il primo modulo, esiste la versione ActiveX (Internet Explorer)
} else if ( window.ActiveXObject ) {
// Vedi spiegazioni sotto
} else {
httpRequest = false;
}
Nel caso di Internet Explorer, bisogna creare un condizionale di tentativi di connessione diversi in quanto la Microsoft ha evoluto (forse meglio dire corretto) l'oggetto ActiveX. In questo caso proviamo a eseguire le connessioni all'oggetto dalla più evoluta a quella standard:
try { httpRequest = new ActiveXObject("MSXML2.XMLHTTP.3.0"); }
catch (e) {
try { httpRequest = new ActiveXObject("MSXML2.XMLHTTP"); }
catch (e) {
try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (e) { httpRequest = false; }
}
}
Come possiamo notare nel codice sopra, il codice utilizza i comandi
try{} e
catch(e){} per verificare la possibilità ad accedere all'oggetto. Nel caso il richiamo dell'oggetto generasse errore, questi non verrebbe gestito dal browser come errore JS.
Nel caso non riusciamo in nessun modo ad accedere al nostro oggetto di connessione remota, avremo la nostra variabile
httpRequest settata a false.
A parte il codice iniziale, tutte le altre operazioni che andremo ad eseguire hanno la stessa identica sintassi. Qui non c'è molto da capire, c'è solo da prendere il codice ed utilizzarlo nelle proprie pagine per inizializzare la richiesta verso il server.
Una volta creato il nostro oggetto
httpRequest, JS è ora abilitato alla connessione remota verso il nostro server. A questo punto possiamo decidere se la nostra transazione avverrà con la modalità GET (quella standard) oppure con la modalità POST:
httpRequest.open("GET", URL, modalita);
oppure
httpRequest.open("POST", URL, modalita);
httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Nel caso decidessimo di effettuare una connessione
POST dovremmo necessariamente inviare anche l'header (come scritto sopra) per far capire al nostro server il modo con cui riceverà i dati. Il tipo "application/x-www-form-urlencoded" è l'enctype standard con cui vengono inviati i form attraverso internet.
La funzione
setRequestHeader serve per passare qualsiasi informazione all'header della richiesta senza alcun vincolo.
Il terzo parametro della funzione
open() corrisponde alla modalità con la quale vogliamo effettuare la richiesta al nostro server:
sincrona o
asincrona:
1) mettiamo
true per la modalità asincrona
2) mettiamo
false per la modalità sincrona
Se utilizziamo la modalità
sincrona JS invia una richiesta per volta al server e fino a che non riceve risposta non invia altre richieste.
Esistono anche un 4° e 5° parametro da passare alla funzione, omessi da me perchè a mio avviso inutili: username e password.
Dato che la connessione con questo metodo permette anche l'accesso ad aree riservate sul server, questi 2 parametri permettono l'accesso a queste aree. Sconsiglio vivamente l'utilizzo in quanto chiunque sarebbe in grado di recuperare i dati di accesso, semplicemente leggendo il vostro script.
Concludendo se volessimo richiamare la nostra pagina "pippo.php" sul server con metodo GET in modalità asincrona, dovremmo scrivere:
httpRequest.open("GET", "/path_to/pippo.php", true);
Per essere pignoli, anche la richiesta remota possiamo inserirla in una condizione
try / catch in modo tale da trappare l'errore se per caso il server non risponde.
N.B. nella URL non siamo obbligati a chiamare una pagina PHP, ma potremmo chiamare semplicemente una pagina HTML o un file TXT:
- httpRequest.open("GET", "/testi/testo.txt", true);
- httpRequest.open("GET", "/index.html", true);
Eventuali parametri che volessimo passare alla nostro server, li possiamo codificare direttamente nella URL che richiamiamo:
/pippo.php?variabile=valore&variabile2=valore2&...
A.A.A. ricordatevi che il valore delle variabili se è alfanumerico va sempre escappato con la funzione apposita, onde evitare errori:
var valore = "sono = a te ?";
URL = "/pippo.php?variabile=" + escape(valore);
Nell'esempio sopra se aganciassimo la variabile
valore senza escapparla, genereremmo una URL non valida e il browser andrebbe in errore.
Una volta aperta la connessione con il server ed inviata la richiesta della pagina, dobbiamo procedere con l'invio dei nostri parametri, semplicemente utilizzando:
httpRequest.send('');
per tutte le connessioni GET, mentre per le connessioni POST sarebbe meglio evitare di inserire i parametri all'interno della URL (come indicato sopra), ma inserirli direttamente nel comando:
httpRequest.send( parametri);
Se prendessimo come esempio l'esempio inserito poco sopra, la nostra richiesta POST diventerebbe:
var valore = "sono = a te ?";
var valore2 = "qualcosa!";
httpRequest.open("POST", "/pippo.php", true);
httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
httpRequest.send("variabile=" + escape(valore) + "&variabile2=" + escape(valore2));
La differenza è che le variabili vengono codificate prima di essere inviate alla URL. Ricordatevi che in base al metodo di connessione utilizzato, anche le variabili in PHP ne risentono:
- se usate GET le variabili PHP saranno contenute nell'array
$_GET[]
- se usate POST le variabili PHP saranno contenute nell'array
$_POST[]
Ora che siamo riusciti ad inviare una richiesta al nostro server, dobbiamo metterci in attesa della risposta con l'oggetto
readyState che contiene il codice di "interazione con il server". Nello schema seguente vediamo quali sono gli stati possibili della nostra connessione:
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete
L'unico stato che a noi interessa è il numero
4 ovvero che la richiesta è andata a buon fine. Tutti gli altri stati sono stati di errore, quindi provando a scrivere il codice per questo comando:
switch ( httpRequest.readyState ) {
case 1,2,3:
alert('Errore di comunicazione: ' + httpRequest.status);
break;
case 4:
if ( httpRequest.status != 200 ) {
alert('Il server ha risposto con l'errore: ' + httpRequest.status);
} else {
// OK abbiamo il nostro risultato
}
break;
}
Nel codice sopra abbiamo aggiunto anche l'oggetto
status che non è altro che l'errore che ci invia il server. I codici d'errore sono quelli standard ( 404 pagina non trovata, 403 permesso negato, ecc.). Volendo stampare anche il testo dell'errore, possiamo utilizzare l'oggetto
statusText, cioè utilizzato verrebbe scritto:
alert("Il server ha risposto: " + httpRequest.statusText);
Per quello che serve a noi, il codice 200 indica "OK", quindi vuol dire che il server ci ha inviato il risultato della nostra richiesta.
Ora sta a noi decidere cosa dobbiamo farne dei dati ricevuti, o meglio, dobbiamo sapere se i dati che abbiamo ricevuto sono in formato XML oppure in formato testo (HTML, TXT, ecc..). Sapendo cosa abbiamo ricevuto, possimo utilizzare 2 oggetti diversi:
-
httpRequest.responseText per i formati "ASCII"
-
httpRequest.responseXML per il formato XML
Nel secondo caso (XML) utilizzando l'oggetto
responseXML il nostro risultato sarà convertito automaticamente in DOM, ovvero verrà generato un oggetto JS contenente i nostri dati.
Come leggere i dati contenuti nel nostro ogetto sarà tema di un altro capitolo del corso.
In conclusione, se dovessimo unire tutte le parti di codice viste in questa pagina, otterremmo come risultato il codice seguente:
if ( window.XMLHttpRequest ) {
httpRequest = new XMLHttpRequest();
} else if ( window.ActiveXObject ) {
try { httpRequest = new ActiveXObject("MSXML2.XMLHTTP.3.0"); }
catch (e) {
try { httpRequest = new ActiveXObject("MSXML2.XMLHTTP"); }
catch (e) {
try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (e) { httpRequest = false; }
}
}
} else {
httpRequest = false;
}
if ( httpRequest ) {
try {
httpRequest.open("POST", URL, true);
httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
httpRequest.send( parametri);
} catch (e) {
alert("Impossibile inviare la richiesta al server");
}
switch ( httpRequest.readyState ) {
case 1, 2, 3:
alert("Errore di comunicazione: " + httpRequest.status);
break;
case 4:
if ( httpRequest.status != 200 ) {
alert("Il server ha risposto con l'errore: " + httpRequest.status);
} else {
var risultato = httpRequest.responseXML;
}
break;
}
} else {
alert("Il browser non supporta connessioni XMLHttpRequest");
}
Questo codice è il codice standard che viene utilizzato per inviare una richiesta al server utilizzando AJAX. Naturalmente il codice preso così non funzionerà (bisogna sostituire alcuni parametri con valori veri). Nella prossima lezione metteremo in pratica quanto acquisito in questa lezione provando a inviare una richiesta semplice al nostro server e stampare la risposta che ci viene ritornata.
Vi ricordo che per qualsiasi chiarimento è a disposizione il forum!
Alla prossima lezione.