Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Iniziare

 

Questo articolo spiega le fondamenta di AJAX e fornisce due semplici esempi per iniziare.

Cos'è AJAX?

AJAX (Asynchronous JavaScript and XML) è un termine coniato recentemente per descrivere due utili funzionalità che sono presenti nei browser da anni, ma che sono state sottovalutate dalla maggioranza degli sviluppatori web fino a quando, di recente, alcune applicazioni come Gmail, Google suggest e Google Maps le hanno portate in auge.

Le funzionalità di cui stiamo parlando sono:

  • la possibilità di eseguire richieste al server senza ricaricare la pagina
  • la possibilità di interpretare e lavorare con i documenti XML

Passo 1 – Dì "per favore", o Come fare una richiesta HTTP

Per effettuare una richiesta HTTP al server utilizzando JavaScript, si utilizza un'istanza di una classe che fornisce detta funzionalità. Tale classe è stata introdotta originariamente in Internet Explorer come oggetto ActiveX e si chiamava XMLHTTP. Successivamente Mozilla, Safari e altri browser hanno implementato la classe XMLHttpRequest, che supporta gli stessi metodi e le stesse proprietà della classe di Microsoft.

Il risultato è che per creare un'istanza (oggetto) da tale classe che funzioni sui diversi browser, occorre scrivere un codice simile al seguente:

if (window.XMLHttpRequest) { // Mozilla, Safari, ...
    http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
    http_request = new ActiveXObject("Microsoft.XMLHTTP");
}

(Per scopi illustrativi, il codice qui riportato è una versione leggermente semplificata del codice generalmente utilizzato per creare un'istanza XMLHTTP. Per un esempio più pratico, si veda il Passo 3 di questo articolo)

Certe versioni di alcuni browser della famiglia Mozilla, non si comportano correttamente nel caso in cui la risposta del server non contiene un'intestazione HTTP mime-type. Per ovviare a questo problema, è possibile utilizzare un metodo aggiuntive per sovrascrivere l'header inviato dal server, nel caso non sia presente o non sia impostato a text/xml.

http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');

Dopodichè occorre decidere cosa fare con la risposta inviata dal server. Quindi bisogna dire all'oggetto XMLHttpRequest quale funzione JavaScript elaborerà il codice XML. Questo si fa impostando la proprietà onreadystatechange dell'oggetto con il nome della funzione JavaScript, in questo modo:

http_request.onreadystatechange = nomeFunzione;

Si noti che non ci sono parentesi dopo il nome della funzione e non viene passato alcun parametro, perchè si sta semplicemente assegnando un riferimento alla funzione, non la si sta ancora chiamando. Inoltre, invece di passare il nome di una funzione, si potrebbe utilizzare la tecnica JavaScript di definire funzioni "al volo" e di definire le azioni che elaboreranno la risposta XML, in questo modo:

http_request.onreadystatechange = function(){
    // azioni da eseguire...
};

Dopo aver dichiarato ciò che accadrà quando si riceverà la risposta dal server, occorre inviare la richiesta. Bisogna chiamare i metodi open() e send() della classe che esegue le richieste, in questo modo:

http_request.open('GET', 'https://www.esempio.org/qualsiasi.file', true);
http_request.send(null);
  • Il primo parametro da passare a open() è il metodo che si desidera utilizzare per la richiesta HTTP: GET, POST, HEAD o qualsiasi altro metodo che si desideri utilizzare e sia supportato dal server. Il metodo deve essere scritto in lettere MAIUSCOLE, come specificato dallo standard HTTP; altrimenti alcuni browser (come Firefox) potrebbero non eseguire la richiesta. Per ulteriori informazioni sui possibili metodi da utilizzare si veda le: specifiche del W3C
  • Il secondo parametro è l'URL della pagina che si sta richiedendo. Per ragioni di sicurezza, non è possibile chiamare pagine che si trovino su un dominio differente da quello in cui si trova la pagina corrente. Bisogna anche assicurarsi di utilizzare esattamente lo stesso dominio in tutte le pagine o si avrà un errore di 'permission denied' quando si chiama il metodo open(). Un errore comune è quello di accedere al sito da <tt>dominio.org</tt> e cercare poi di chiamare pagine che si trovano su <tt>www.dominio.org</tt>
  • Il terzo parametro specifica se la richiesta deve essere asincrona. Se è impostato a TRUE (e di solito è così), la funzione JavaScript resterà in esecuzione anche prima dell'arrivo della risposta.

Il parametro del metodo send() è costituito dai dati che si vogliono inviare al server se la richiesta è di tipo POST. I dati vengono passati sotto forma di querystring, così:

nome1=valore1&nome2=valore2&ecc=ecc

Si noti che se si desidera inviare i dati come POST, occorre modificare il tipo MIME della richiesta con la riga seguente:

http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

In caso contrario, il server ignorerà la richiesta.

Step 2 – "Via!" o Come gestire la risposta del server

Come si è detto, all'atto di inviare la richiesta, si è fornito il nome della funzione JavaScript che deve elaborare la risposta.

http_request.onreadystatechange = nomeFunzione;

Ma cosa dovrebbe fare questa funzione? Primo, la funzione deve controllare lo stato della richiesta. Se lo stato ha un valore di 4, significa che la risposta è stata ricevuta per intero e si può continuare l'elaborazione:

 

if (http_request.readyState == 4) {
    // tutto a posto, la risposta è stata ricevuta
} else {
    // non sono ancora pronto
}

Ecco la lista completa dei possibili valori di readyState:

  • 0 (non inizializzato)
  • 1 (sta caricando)
  • 2 (già caricato)
  • 3 (interattivo)
  • 4 (completato)

(Fonte) (1)

Bisognerà poi controllare il codice di stato della risposta HTTP. Tutti i codici possibili sono elencati nel sito del W3C. Per i nostri scopi, ci interessa soltanto il codice 200 OK.

if (http_request.status == 200) {
    // perfetto!
} else {
    // c'è stato un problema nella richiesta,
    // per esempio un codice di errore 404 (Not Found)
    // o 500 (Internal Server Error)
}

Una volta controllati lo stato della richiesta e il codice di stato HTTP della risposta, sarà lo sviluppatore a decidere cosa desidera fare con i dati ricevuti dal server. Per accedere ad essi, vi sono due possibilità:

  • http_request.responseText – restituisce la risposta sotto forma di stringa di testo
  • http_request.responseXML – restituisce la risposta sotto forma di oggetto XMLDocument che si può navigare tramite le funzioni DOM.

Passo 3 - "Tutti insieme ora!", Un semplice esempio

Vediamo ora tutti gli elementi esaminati finora combinati insieme. Il seguente JavaScript richiede un documento HTML (test.html), che contiene il testo "Sono un test.", e farà un alert() coi contenuti di questo file.

<script type="text/javascript" language="javascript">

    

    function eseguiRichiesta(url) {

        var http_request = false;

        if (window.XMLHttpRequest) { // Mozilla, Safari,...
            http_request = new XMLHttpRequest();
            if (http_request.overrideMimeType) {
                http_request.overrideMimeType('text/xml');
                // Vedi note sotto
            }
        } else if (window.ActiveXObject) { // IE
            try {
                http_request = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    http_request = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {}
            }
        }

        if (!http_request) {
            alert('Giving up :( Non riesco a creare una istanza XMLHTTP');
            return false;
        }
        http_request.onreadystatechange = function() { alertContents(http_request); };
        http_request.open('GET', url, true);
        http_request.send(null);

    }

    function alertContents(http_request) {

        if (http_request.readyState == 4) {
            if (http_request.status == 200) {
                alert(http_request.responseText);
            } else {
                alert('Si è verificato un problema con la richiesta');
            }
        }

    }
</script>
<span
    style="cursor: pointer; text-decoration: underline"
    onclick="eseguiRichiesta('test.html')">
        Fai una richiesta
</span>

In questo esempio:

  • L'utente clicca sul link "Fai una richiesta";
  • Viene chiamata la funzione eseguiRichiesta() con un parametro: il nome del file test.html, che si trova nella stessa directory;
  • Il browser esegue la richiesta e l'esecuzione passa a alertContents();
  • alertContents() controlla se l'esecuzione è stata ricevuta e se lo stato della risposta è OK: in caso affermativo chiama un alert() con i contenuti del file test.html.

Si può provare questo esempio qui e si può leggere il file "test.html" qui.

Nota: La riga di codice http_request.overrideMimeType('text/xml'); causa degli errori nella Console JavaScript di Firefox 1.5 o superiore nel caso che la pagina chiamata non sia costituita da XML ben formato (come in questo caso). Questo comportamento è corretto ed è documentato qui: https://bugzilla.mozilla.org/show_bug.cgi?id=311724 - l'articolo verrà rivisto per correggere questo errore.

Nota 2: se si invia una richiesta con una porzione di codice che restituisce XML e non un file XML statico, bisogna impostare alcune intestazioni nella risposta perchè la pagina funzioni anche su Internet Explorer. Se non si imposta l'intestazione Content-Type: application/xml, IE lancia un errore JavaScript 'Object Expected' appena si cerca di accedere a un elemento XML. Se non si imposta l'intestazione Cache-Control: no-cache, il browser registra la risposta nella cache e non rieseguirà più la richiesta, il che fa impazzire molti sviluppatori in fase di debugging.

Nota 3: se la variabile http_request è globale, se vi sono altre funzioni che chiamano makeRequest(), possono sovrasciversi a vicenda. Per evitare questo problema, occorre dichiarare questa variabile come locale e passarla alla funzione alertContent().

Nota 4: nel registrare la funzione callback per onreadystatechange non è possibile passare alcun argomento:

http_request.onreadystatechange = function() { alertContents(http_request); };  //1 (richiesta simultanea)
http_request.onreadystatechange = alertContents(http_request); //2 (non funziona)
http_request.onreadystatechange = alertContents;  //3 (variabile globale)

Il metodo 1 permette di elaborare diverse richieste simultaneamente. Il metodo 2 non funziona. Il metodo 3 è da utilizzare se http_request è una variabile globale.

Passo 4 - "Gli X-Files", o Elaborare la risposta XML

Nell'esempio precedente, dopo che la risposta HTTP è stata ricevuta si è utilizzata la proprietà reponseText dell'oggetto richiesta, che conteneva i contenuti del file <tt>test.html</tt>. Proveremo ora a utilizzare la proprietà responseXML.

Prima di tutto, occorre creare un documento XML valido che verrà chiamato in seguito. Il documento (<tt>test.xml</tt>) contiene quanto segue:

<?xml version="1.0" ?>
<root>
    Sono un test.
</root>

Nello script occorre cambiare soltanto la riga seguente:

...
onclick="eseguiRichiesta('test.xml')">
...

In alertContents(), bisogna poi sostituire la riga alert(http_request.responseText); con:

var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);

Questo codice prende l'oggetto XMLDocument fornito da responseXML e utilizza i metodi DOM per accedere ai dati contenuti nel documento XML. Si può vedere test.xml qui. Si può vedere in azione questa versione dello script qui.

Per ulteriori dettagli sui metodi DOM, si vedano i documenti sull'Implementazione DOM di Mozilla.


La bozza di standard del W3C indica i seguenti valori per la proprietà readystate:

  • 0 Non inizializzato: il valore iniziale
  • 1 Aperto: il metodo open() è stato chiamato con successo
  • 2 Inviato: il browser a completato la richiesta con successo, ma ancora non ha ricevuto alcun dato in risposta
  • 3 Ricezione: immediatamente prima di ricevere il corpo del documento (se esiste). Tutte le intestazioni HTTP sono state ricevute (la bozza pone però un quesito: come comportarsi con le richieste di tipo HEAD?)
  • 4 Caricato: il trasferimento dei dati è stato completato

Fonte

Tag del documento e collaboratori

 Hanno collaborato alla realizzazione di questa pagina: Mattia_Zanella, Federico
 Ultima modifica di: Mattia_Zanella,