- Introduzione ad AJAX: richieste sincrone ed
asincrone - |
|||
COSA SERVE PER QUESTO TUTORIAL | |||
Download | Chiedi sul FORUM | Glossario | Conoscenze basiche di HTML e Javascript | ||
Cos'è e come funziona AJAX | |||
MITI DI AJAX Favole e realtà sulla tecnica AJAX è acronimo di
Asynchronous Javascript And XML, una tecnica di programmazione ormai
sempre più diffusa sul web. Prima cosa dunque è una tecnica e non un
linguaggio: si basa su JS, il diffusissimo linguaggio di scripting lato
client, e fa uso di alcune funzionalità per comunicare asincronamente
(ovvero senza cambiare pagina) con il server attraverso, in maniera preferenziale ma non necessaria,
XML. In sostanza usare AJAX significa programmare in Javascript
utilizzando l'oggetto XMLHttpRequest. Uno dei principali svantaggi delle applicazioni web rispetto a quelle desktop è il
fatto che nelle prime ogni input dell'utente per essere interpretato
deve essere inviato al server, creando l'inconveniente di dover far
scaricare una nuova pagina all'utente, con una notevole perdita di
tempo. AJAX è nato per colmare questa differenza: è possibile infatti
inviare e richiedere dati al server remoto attraverso Javascript, così
eliminando la necessità di ricaricare la pagina. Per prima cosa bisogna dire che l'oggetto XMLHttpRequest (come detto,
il cuore di AJAX) può essere utilizzato in maniera sincrona o asincrona:
nel primo caso l'esecuzione del codice viene interrotta, bloccando il
browser temporaneamente fino al completamento della richiesta, mentre
nel secondo, una volta eseguita la richiesta tutto funziona normalmente e
al compimento dell'operazione viene richiamato
l'evento onreadystatechange. <div class="menu">Menu<br></div> <div id="content" class="content">DIV del contenuto</div> All'interno del menu poniamo un certo numero di link simili a quelli che seguono, incrementando l'indice del contenuto (che ci servirà poi per sapere quale file richiedere, come pagina1.txt, pagina2.txt ecc., che naturalmente devono esistere e contenere qualche testo): <a href="pagina1.htm" onclick="return CaricaContenuto(1);">Pagina 1</a><br> <a href="pagina2.htm" onclick="return CaricaContenuto(2);">Pagina 2</a><br> <a href="pagina3.htm" onclick="return CaricaContenuto(3);">Pagina 3</a><br> [...] Al click su uno di essi viene eseguita la funzione CaricaContenuto
che inoltra la richiesta dei dati al server e scrive la risposta
all'interno del DIV del contenuto. Si noti il fatto che nell'evento onClick
viene restituito il valore a sua volta restituito da CaricaContenuto: se
dall'evento onClick si restituisce false il link viene ignorato e dunque non vi è reindirizzamento, se invece viene restituito
true, l'anchor si comporta
normalmente. CaricaContenuto è predisposto in modo tale da restituire
true quando rileva che AJAX (ovvero l'oggetto XMLHttpRequest) non è
supportato dal browser. Questa tecnica permette ai browser senza
supporto per Javascript o per XMLHttpRequest di essere reindirizzati ad
una pagina statica, se così non fosse, per essi sarebbe impossibile
visitare il sito. // Funzione richiamata quando si clicca su un link del menu, richiede al // server e mostra i dati in questione function CaricaContenuto(id) { // Otteniamo l'oggetto XMLHttpRequest var request = GetXMLHttpRequest() // Nel caso AJAX non sia supportato restituisce true, il che permette // di essere reindirizzati al file specificato nell'href, infatti il // valore restituito dall'evento onClick indica se ignorare href o // meno if (request == null) return true; // Predispone una richiesta di tipo GET a pagina#.txt sincrona (ultimo // parametro false), ovvero arresta l'esecuzione fino al // completamento dell'operazione request.open("GET", "pagina" + id + ".txt", false); // Esegue l'operazione senza inviare alcun dato specifico request.send(null); // Se l'operazione ha avuto successo (codice HTTP 200) sostituisce // il contenuto del DIV "content" con il testo scaricato altrimenti // mostra codice e testo dell'errore if(request.status == 200) { document.getElementById("content").innerHTML = request.responseText; } else { alert("Si è verificato un errore: \n" + request.status + " - " + request.statusText) } return false; } Sostanzialmente essa tenta di creare XMLHttpRequest con la funzione GetXMLHttpRequest, che vedremo in dettaglio tra poco. Se quest'ultima ha come risultato null, AJAX non è supportato, dunque CaricaContenuto restituisce true (quindi, come appena detto, il link si comporterà normalmente, reindirizzando ad un file HTML statico); in caso contrario predispone la richiesta XMLHttpRequest con il metodo open e la inoltra con send. Come si può vedere a open vengono comunicati il tipo di richiesta, l'URL desiderato, e un valore booleano che indica se la richiesta deve essere asincrona (true) o meno (false). I tipi di richiesta sono tipicamente tre (ma in questo articolo ci occuperemo solamente della prima):
Essendo la richiesta sincrona, il codice si blocca su send fino al
completamento dell'operazione. A questo punto viene verificato il risultato
attraverso la proprietà status che rappresenta il codice HTTP della
risposta del server: ad esempio 200 indica che l'operazione è riuscita,
404 che il file richiesto non esiste e così via. Se non vi sono errori
(codice HTTP 200, appunto), il contenuto del DIV con ID content viene rimpiazzato
con il responso della richiesta, ottenuto tramite la proprietà
responseText. In caso di errori si notifica testo e codice di risposta
all'utente. Infine, dato che AJAX è supportato, viene restituito false. // Funzione che ottiene (nelle sue varie forme a seconda del browser) // l'oggetto XMLHttpRequest function GetXMLHttpRequest() { var obj; // Dichiariamo una variabile che indica se l'oggetto è stato creato // o meno dato che si procederà per tentativi var creato = false; try { // Crea l'oggetto XMLHttpRequest (funziona con Firefox, Mozilla, // Opera, Safari e Internet Explorer dalla 7) obj = new XMLHttpRequest(); creato = true; } catch (e) { // Per le versioni precedenti alla 7 di IE si procede tentando di // creare l'oggetto ActiveX XMLHttpRequest, che assume nomi diversi // a seconda delle versioni var IEXMLHttpRequestNames = new Array("Microsoft.XmlHttp", "MSXML4.XmlHttp", "MSXML3.XmlHttp", "MSXML2.XmlHttp", "MSXML.XmlHttp"); for (var i = 0; i < IEXMLHttpRequestNames .length; i++) { try { obj = new ActiveXObject(IEXMLHttpRequestNames[i]); creato = true; } catch (e) { } } } // Se è stato possibile creare l'oggetto lo restituisce altrimenti // da come risultato null if (creato) { return obj; } else { return null; } } La funzione GetXMLHttpRequest, tenta di creare XMLHttpRequest utilizzando
dapprima un semplice new XMLHttpRequest (per IE dalla versione 7,
Mozilla, Firefox, Opera e Safari), poi tenta di creare l'ActiveX (per le
versioni di IE precedenti alla 7) con nomi diversi finché non vi riesce.
Se nessuno di questi metodi
ha successo, AJAX non è supportato, dunque viene restituito null. RICHIESTE ASINCRONE In precedenza abbiamo detto che vi è anche la possibilità di effettuare la richiesta al server in maniera asincrona, dunque senza bloccare l'esecuzione, metodo leggermente più complesso ma indispensabile in caso di scarsa connettività o di necessità di dover scaricare grosse quantità di dati. Per eseguire la richiesta asincronamente dobbiamo servirci dell'evento onreadystatechange che viene chiamato ogni volta che cambia lo stato di avanzamento della richiesta, identificato dalla proprietà readyState. readyState che può assumere i seguenti valori: richiesta non iniziata (0), invio richiesta (1), richiesta inviata (2), alcuni dati ricevuti (3), richiesta completata (4). Mettiamo dunque un riferimento ad una nuova funzione chiamata request_readystatechange nella function di creazione dell'oggetto XMLHttpRequest; prima di return obj in GetXMLHttpRequest aggiungiamo quanto segue: // Impostiamo request_readystatechange come gestore dell'evento // onreadystatechange obj.onreadystatechange = request_readystatechange; Ed ecco di seguito la funzione request_readystatechange: // Funzione richiamata quando l'operazione di richiesta AJAX cambia il suo stato: // non iniziata (0), invio richiesta (1), richiesta inviata (2), alcuni dati // ricevuti (3), richiesta completata (4). In questo caso ci interesseremo solo // all'ultima evenienza function request_readystatechange() { // Quando è stata completata l'operazione (readyState 4) if (request.readyState == 4) { // Se l'operazione ha avuto successo (codice HTTP 200) sostituisce // il contenuto del DIV "content" con il testo scaricato altrimenti // mostra codice e testo dell'errore if(request.status == 200) { document.getElementById("content").innerHTML = request.responseText; } else { alert("Si è verificato un errore: \n" + request.status + " - " + request.statusText) } } } Questa funzione verrà richiamata in varie occasioni con readyState diversi, ma noi siamo in questo caso interessati solo a essere notificati del completamento dell'operazione (request.readyState == 4); il codice all'interno del blocco if che verifica il readyState è uguale in tutto e per tutto a quello che seguiva il metodo send nella funzione CaricaContenuto, da cui va eliminato. CaricaContenuto risulterà quindi così: // Funzione richiamata quando si clicca su un link del menu, richiede al // server e mostra i dati in questione function CaricaContenuto(id) { // Otteniamo l'oggetto XMLHttpRequest request = GetXMLHttpRequest() // Nel caso AJAX non sia supportato restituisce true, il che permette // di essere reindirizzati al file specificato nell'href, infatti il // valore restituito dall'evento onClick indica se ignorare href o // meno if (request == null) return true; // Predispone una richiesta di tipo GET a pagina#.txt asincrona (ultimo // parametro true), ovvero non arresta l'esecuzione: la conclusione // dell'operazione verrà segnalata a request_readystatechange request.open("GET", "pagina" + id + ".txt", true); // Esegue l'operazione senza inviare alcun dato specifico request.send(null); return false; } Una volta richiamato send l'esecuzione del codice continua e la richiesta viene portata a termine in background. Si noti che il terzo parametro della chiamata a open è questa volta true: ciò indica che la richiesta deve essere asincrona. Inoltre è necessario spostare la dichiarazione di request (l'oggetto XMLHttpRequest) a livello globale, cosicché sia accessibile anche da request_readystatechange. Porre quindi la dichiarazione di request in cima allo script: <script type="text/javascript" language="javascript"> // L'oggetto request è globale perché sia accessibile anche da // request_readystatechange var request; CONCLUSIONI In questo articolo abbiamo visto come AJAX può rivoluzionare la
programmazione web grazie all'eliminazione della tradizionale necessità
di ricaricare le pagine. Le applicazioni di questa tecnica possono
essere molte altre, dalla validazioni di campi in tempo reale ad una
chat, dalla notifica dei movimenti dell'utente al classico completamento
automatico.
È stata poi data una panoramica dei due metodi, sincroni o asincroni, e
delle loro differenze: si ricordi a questo proposito che è in genere
preferibile utilizzare il metodo asincrono così da non arrestare
l'esecuzione dell'intero browser. |
|||
<< INDIETRO | by VeNoM00 |