Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 90 di 112
  • livello avanzato
Indice lezioni

Ajax e JavaScript

Ajax permette di effettuare richieste al server e manipolare dati senza ricaricare la pagina Web e in maniera asincrona.
Ajax permette di effettuare richieste al server e manipolare dati senza ricaricare la pagina Web e in maniera asincrona.
Link copiato negli appunti

Una delle limitazioni delle pagine Web di qualche anno fa era l'impossibilità di interagire direttamente con il server ed aggiornare i contenuti senza dover ricaricare la pagina.

Le API di comunicazione

Oggi queste limitazioni sono state superate grazie a delle API standard che consentono una certa flessibilità nell'interazione con il server usando JavaScript. In questa sezione vedremo le tre principali API di comunicazione disponibili per una pagina Web per interagire con il server: Ajax, Server-Sent Events e WebSocket.

Ajax

La possibilità di comunicare con il server tramite codice dall'interno di una pagina Web è stato uno dei principali motivi della rinascita di JavaScript. La tecnologia nota come Ajax (Asynchronous JavaScript And XML) rappresenta la rivisitazione di tecnologie esistenti sotto una nuova luce, con l'obiettivo di consentire di inviare e ricevere dati dal server in maniera asincrona e con la possibilità di aggiornare porzioni di una pagina Web.

Anche se l'acronimo fa riferimento a XML come formato di rappresentazione dei dati, in realtà esso non è obbligatorio: infatti una delle rappresentazioni più spesso utilizzate è JSON.

Effettuare una richiesta Ajax

Ajax ruota intorno all'oggetto XMLHttpRequest che rappresenta l'intermediario tra il codice JavaScript eseguito sul browser e il codice eseguito sul server. Questo oggetto mette a disposizione tutti gli strumenti per creare ed inviare richieste HTTP e ricevere ed analizzare le relative risposte.

Quello che segue è un semplice esempio di utilizzo di XMLHttpRequest:

var httpReq = new XMLHttpRequest();
httpReq.onreadystatechange = function() {
	if (httpReq.readyState == 4 && httpReq.status == 200) {
		document.getElementById("myDiv").innerHTML = httpReq.responseText;
	}
};
httpReq.open("GET", "/myServerPage", true);
httpReq.send();

Analizzando il codice vediamo che, dopo aver creato un'istanza del nostro oggetto, abbiamo associato all'evento readystatechange un gestore che ha il compito di catturare la risposta del server ed assegnarla come contenuto del <div> myDiv.

L'evento readystatechange si verifica ad ogni variazione del valore della proprietà readyState di XMLHttpRequest, che rappresenta lo stato di avanzamento della richiesta. I possibili valori di questa proprietà sono:

Valore Descrizione
0 Richiesta non inizializzata
1 Connessione al server stabilita
2 Ricezione degli header HTTP
3 Ricevimento della risposta
4 Operazione completata

Nel nostro caso, quando la risposta ricevuta dal server è completa ed il codice di stato HTTP inviato dal server è 200 (valore che indica che non si sono verificati errori), il contenuto inviato dal server e rappresentato dalla proprietà responseText viene assegnato al <div> myDiv.

Open, aprire una richiesta con HTTP GET

Dopo aver preparato la funzione che gestirà l'evento di risposta, apriamo una connessione HTTP con il server tramite il metodo open(). I parametri che passiamo a questo metodo rappresentano:

  • il verbo HTTP (GET nel nostro caso);
  • l'URL della pagina o dello script server side richiesto;
  • un valore booleano opzionale che indica se la richiesta deve essere effettuata in maniera asincrona (true) o sincrona (false).

Se non è specificato il terzo parametro viene assunto il valore true e la chiamata sarà asincrona. Infine inviamo la richiesta tramite il metodo send().

Nota: se l'interazione con il server è sincrona, cioè il terzo parametro del metodo open() è false, non dobbiamo gestire readystatechange ma possiamo gestire la risposta del server subito dopo l'invocazione del metodo send().

var httpReq = new XMLHttpRequest();
httpReq.open("GET", "/myServerPage", false);
httpReq.send();
if (httpReq.status == 200) {
	document.getElementById("myDiv").innerHTML = httpReq.responseText;
}

Gestire la risposta del server

Nell'esempio che abbiamo analizzato abbiamo ignorato la possibilità che il server ci segnali situazioni di errore. In situazioni reali dobbiamo prevedere questa eventualità e gestire opportunamente i codici di stato inviati dal server. Un possibile modo di gestire la situazione è mostrato di seguito:

var httpReq = new XMLHttpRequest();
httpReq.onreadystatechange = function() {
	if (httpReq.readyState == 4) {
		switch(httpReq.status) {
			case 200:
				document.getElementById("myDiv").innerHTML = httpReq.responseText;
				break; 
			case 404:
				alert("La pagina indicata non esiste!");
				break;
			case 500:
				alert("Si è verificato un errore sul server!");
				break; 
			default:
				alert("Non è possibile elaborare la richiesta (" + httpReq.statusText + ")");
		}
	}
};

Quando la ricezione della risposta è completa viene analizzato il codice di stato ed eseguite le istruzioni corrispondenti. Da notare l'utilizzo della proprietà statusText che rappresenta il testo associato al codice di stato HTTP.

Nel nostro esempio abbiamo utilizzato la proprietà responseText, che restituisce la risposta del server come semplice testo. Se il server invia una risposta in formato XML possiamo utilizzare la proprietà responseXML che restituisce la risposta come documento XML e a cui possiamo applicare i metodi per la relativa manipolazione.

Il seguente esempio mostra come assegnare al <div> myDiv il contenuto dell'elemento rappresentato dal tag testo presente nell'XML inviato dal server:

httpReq.onreadystatechange = function() {
	if (httpReq.readyState == 4) {
		switch(httpReq.status) {
			case 200:
				var xmlDoc = httpReq.responseXML;
				document.getElementById("myDiv").innerHTML = xmlDoc.getElementByTagName("testo")[0].childNodes[0].nodeValue;
				break; 
				...
		}
	}
};

La dicitura XML ha motivazioni storiche: infatti anche un documento HTML è disponibile tramite la proprietà responseXML.

Un approccio più generale all'analisi della risposta del server, soprattutto quando il formato dell'informazione che il server ci invia non è determinato a priori, prevede l'utilizzo delle proprietà responseType e response. La proprietà responseType indica il tipo di dato inviato dal server assumendo uno dei seguenti valori:

Campo Descrizione
text La risposta è in formato testuale
document La risposta è un documento XML o HTML
json La risposta è un oggetto JSON risultante dal parsing di una stringa inviata dal server
arraybuffer La risposta è un un buffer di dati binary rappresentati come ArrayBuffer
blob La risposta è un oggetto Blob, assimilabile ad un file

Una volta determinato il tipo possiamo utilizzare la proprietà response per accedere al contenuto della risposta:

httpReq.onreadystatechange = function() {
	if (httpReq.readyState == 4) {
		switch(httpReq.status) {
			case 200:
				switch(httpReq.responseType) {
					case "text":
						elaboraTesto(httpReq.response);
						break; 
					case "document":
						elaboraDocumento(httpReq.response);
						break;
						...
				}
				break;
				...
		}
	}
};

Gestire gli header HTTP

In alcune situazioni può essere necessario inviare al server degli header HTTP insieme alla richiesta. È ad esempio questo il caso quando si invia una richiesta al server utilizzando il metodo POST, come vedremo più avanti.

In generale, per l'impostazione di un header abbiamo a disposizione il metodo setRequestHeader() che prevede due parametri: il nome dell'header e il suo valore. Il seguente esempio mostra come impostare l'header Accept per indicare al server in quali formati si preferisce ricevere la risposta:

httpReq.setRequestHeader("Accept", "application/json, text/html, text/*");
httpReq.open("GET", "/myServerPage", true);
httpReq.send();

Nel caso specifico abbiamo indicato che si preferiscono nell'ordine il formato JSON, HTML e qualsiasi formato di tipo testo.

Analogamente è possibile analizzare gli header HTTP inviati dal server con la risposta tramite i metodi getAllResponseHeaders() e getResponseHeader(). Il primo metodo restituisce una stringa con tutti gli header inviati dal server, mentre il secondo restituisce il valore per un header specifico.

Il seguente esempio mostra come ottenere le dimensioni in byte della risposta inviata dal server:

var dimensioni = httpReq.getResponseHeader("Content-Length");

Ti consigliamo anche