back to top

jQuery Ajax: gestire chiamate asincrone

In questa lezione passeremo in rassegna uno degli aspetti piรน importanti di questo framework, vedremo cioรจ come utilizzare jQuery per implementare chiamate asincrone mediante la tecnologia Ajax, ma per prima cosa credo sia opportuno spiegare cosโ€™รจ una chiamata asincorona (o "chiamata Ajax").

Cosโ€™รจ Ajax (e a cosa serve)

Si definisce asincrona una chiamata ad una risorsa esterna che non interferisce con lโ€™esecuzione della risorsa chiamante; i risultati della risorsa esterna saranno utilizzabili solo quando disponibili senza "tempi morti" per lโ€™utilizzatore (il caricamento della risorsa esterna avviene in background).

Attraverso Ajax รจ possibile cambiare dinamicamente il contenuto di una pagina o di una sua porzione senza effettuare il ricaricamento della URL, recuperando informazioni "fresche" da una risorsa web, sia essa statica (un file HTML o un XML, ad esempio) che dinamica (uno script PHP, JSP o altro), che viene contattata attraverso una chiamata HTTP lanciata tramite Javascript. E sarร , appunto, Javascript ad occuparsi di gestire eventuali errori e di manipolare il risultato ricevuto in risposta interagendo col DOM del documento.

Una cosa importante da sottolineare รจ che la risorsa contattata tramite Ajax deve essere una risorsa locale. In base alle restrizioni del Same Origin Policy, infatti, non รจ possibile effettuare chiamate Ajax a risorse presenti allโ€™interno di altri domini per questioni di sicurezza.

Diffusione di Ajax

Lโ€™utilizzo di questa tecnica di programmazione (non รจ corretto definire Ajax un linguaggio!) si รจ molto diffuso negli ultimi anni, soprattutto con lโ€™avvento delle nuove applicazioni del Web 2.0 per la cui realizzazione viene chiesto agli sviluppatori di superare i limiti del "web tradizionale" realizzando pagine web sempre piรน simili alle "applicazioni" che vengono installate sui computer (dove non esiste, appunto, il concetto di "refresh di pagina" per ottenere un dato output).

Purtroppo questo tipo di approccio di sviluppo richiede al programmatore un notevole sforzo e la scrittura di molto piรน codice rispetto al solito. Senza un framework di supporto, inoltre, questa pratica puรฒ dirsi proibitiva per chiunque non sia un vero esperto della materia.

Grazie a jQuery, fortunatamente, lโ€™utilizzo di Ajax puรฒ dirsi molto piรน veloce e, soprattutto, molto piรน semplice, tanto da consentire lโ€™utilizzo di questa tecnica anche a chi non conosce minimamente i meccanismi che ne regolano il funzionamento.

Il metodo jQuery.ajax()

Questo metodo, che viene applicato direttamente allโ€™oggetto jQuery, permette di effettuare una chiamata Ajax e di personalizzarla attraverso i molti parametri disponibili.

La chiamata del metodo puรฒ essere effettuata attraverso due differenti sintassi:

// estesa
jQuery.ajax(...)

// abbreviata
$.ajax(...);

I parametri piรน importanti di una chiamata di questo tipo sono sicuramente due:

  • url della risorsa che effettua il lavoro;
  • funzione da eseguire al termine della chiamata.

Come detto esistono una varietร  di parametri che offrono un ulteriore raffinamento della chiamata, nella tabella che segue riassumo i principali parametri ammessi dal metodo .ajax():

  • async (default: true) โ€“ Determina se la chiamata deve essere asincrona (true) o sincrona (false).
  • complete โ€“ Consente di specificare una funzione che verrร  eseguita al termine della chiamata indipendentemente che abbia dato successo o errore; รจ eseguita dopo success o error.
  • data โ€“ Contiene i dati che devono essere inviati alla risorsa che elabora la richiesta; il formato puรฒ essere sotto forma di oggetto (contenente delle coppie chiave/valore) oppure sotto forma di semplice stringa &key1=val1&key2=val2.
  • dataType โ€“ Tipo di dato che si riceve di ritorno; jQuery tenta di capirlo da solo, ma รจ sempre meglio specificarlo. I tipi possibili sono: "xml", "html", "script", "json", "jsonp" e "text".
  • error โ€“ Consente di specificare una funzione che verrร  eseguita in caso di errore nellโ€™effettuare la chiamata.
  • success โ€“ Consente di specificare una funzione che verrร  eseguita al successo della chiamata.
  • timeout โ€“ Eโ€™ possibile impostare una durata massima (in millisecondi) della chiamata; se la risorsa non risponde entro il imite fissato la chiamata viene abortita.
  • type (default: GET) โ€“ Eโ€™ utilizzato per specificare il tipo di richiesta da effettuare, principalmente POST o GET; sono utilizzabili anche altri metodi HTTP (come ad es. PUT, DELETE, โ€ฆ) ma non tutti i browser li supportano.
  • url (default: URL della pagina corrente) โ€“ URL della risorsa alla quale viene inviata la richiesta; se omessa verrร  contattata la pagina corrente.

Vediamo un semplice esempio che mostri come si utilizzano questi parametri:

$.ajax({
  // definisco il tipo della chiamata
  type: "POST",
  // specifico la URL della risorsa da contattare
  url: "/script/utenti.php",
  // passo dei dati alla risorsa remota
  data: "nome=giovanni&cognome=belelli",
  // definisco il formato della risposta
  dataType: "html",
  // imposto un'azione per il caso di successo
  success: function(risposta){
    $("div#risposta").html(risposta);
  },
  // ed una per il caso di fallimento
  error: function(){
    alert("Chiamata fallita!!!");
  }
}

NOTA: lโ€™ordine dei parametri passati al metodo .ajax() non รจ assolutamente rilevante.

Il codice qui sopra รจ ampiamente commentato, tuttavia desidero soffermarmi ulteriormente sul parametro data.

Nel nostro esempio abbiamo passato questa stringa:

data: "nome=giovanni&cognome=belelli"

ma avremmo anche potuto passargli unโ€™oggetto composto da coppie di chiavi e valori:

data: { 'nome' : 'giovanni', 'cognome' : 'belelli' }

Se avessimo voluto recuperare dinamicamente i dati da due campi input di un form (ciascuno contraddistinto da un ID univoco) avremmo utilizzato un codice del genere:

data: "nome=" + $('input#nome').val() + "&cognome=" + $('input#cognome').val()

oppure:

data: { nome: $('input#nome').val(), cognome: $('input#cognome').val() }

Esempio pratico di utilizzo di $.ajax()

Segue un esempio completo di un rudimentale modulo dโ€™iscrizione realizzato in Ajax che offre una visione pratica dei semplici esempi visti sopra:

<html>  
  <head>  
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script type="text/javascript">  
    $(document).ready(function() {  
      $("form#iscrizione").submit(function(){  
        var nome = $("#nome").val();  
        var cognome = $("#cognome").val();  
        $.ajax({  
          type: "POST",
          url: "/script/utenti.php",  
          data: "nome=" + nome + "&cognome=" + cognome,
          dataType: "html",
          success: function(risposta) {  
            $("div#risposta").html(risposta);  
          },
          error: function(){
            alert("Chiamata fallita!!!");
          } 
        }); 
        return false;  
      });
    });
    </script>  
  </head>  
  <body>  

    <form id="iscrizione">
    <p>
      Inserisci il nome:<br/>
      <input type="text" name="nome" id="nome"/>
    </p>
    <p>
      Inserisci il cognome:<br/>
      <input type="text" name="cognome" id="cognome"/>
    </p>
    <p>
      <input type="submit" value="invia">
    </p>
    </form>

    <div id="risposta"></div>  

  </body> 
</html>

Questo semplice script intercetta il submit del form da parte dellโ€™utente ed estrae il valore die campi incapsulandolo allโ€™interno di due variabili che poi vengono passati ad una risorsa esterna che restituirร  una risposta formattata ion HTML. Tale risposta sarร  mostrata allโ€™interno del DIV con ID "risposta" senza alcun refresh di pagina.

Alcune precisazioni in merito al parametro "error" di $.ajax()

Onde evitare confusioni รจ bene puntualizzare che lโ€™evento error (parametrizzato nel metodo ajax()) non รจ da confondere con la mancata riuscita di unโ€™operazione da parte della risorsa contattata (quella indicata, cioรจ, nel parametro url). Gli errori di questโ€™ultima, infatti, non attengono alla nostra chiamata Ajax la quale, in tale circostanza, produrrร  semplicemente un output diverso da quello atteso. Lโ€™errore cui facciamo riferimento, quindi, รจ quello della chiamata stessa! Un tipico esempio รจ dato dallโ€™impossibilitร  di accedere alla risorsa remota perchรจ inseistente (errore 404) o, comunque, non accessibile a causa di un errore, del temporaneo malfunzionamento del server o della Rete.

I metodi .done(), .fail() e .always()

A partire dalla versione 1.5 di jQuery il metodo Ajax restituisce un superset che prende il nome di jqXHR (jQuery XMLHttpRequest) il quale costituisce unโ€™estensione dellโ€™oggetto XMLHttpRequest. Possiamo sfruttare questa possibilitร , ad esempio, creando una variabile a cui assegniamo il valore restituito dal metodo .ajax() in questo modo:

var jqxhr = $.ajax(...)

Attraverso questa variabile, poi, sarร  possibile accedere ad alcuni interessanti metodi come:

  • .done() โ€“ รจ unโ€™alternativa al parametro success del metodo .ajax();
  • .fail() โ€“ รจ unโ€™alternativa al parametro error del metodo .ajax();
  • .always() โ€“ รจ unโ€™alternativa al parametro complete del metodo .ajax();

Il vantaggio di questi metodi consiste nel fatto che vengono "portate fuori" dal metodo .ajax() alcune operazioni che potranno essere eseguite anche in un secondo momento. Tornando allโ€™esempio del nostro modulo di iscrizione avremmo potuto scrivere:

$("form#iscrizione").submit(function(){  
  var nome = $("#nome").val();  
  var cognome = $("#cognome").val();  
  var jqxhr = $.ajax({  
    type: "POST", 
    url: "/script/utenti.php",  
    data: "nome=" + nome + "&cognome=" + cognome
  });
  
  // ... qui se voglio posso mettere altro codice javascript ...
  
  // qui mostro il risultato della chiamata Ajax
  jqxhr.done(function(risposta) {  
    $("div#risposta").html(risposta);  
  }).fail(function(){
    alert("Chiamata fallita!!!");
  }); 
  return false;  
});

Oltre ai metodi citati, attraverso lโ€™oggetto jqXHR รจ possibile accedere a diversi metodi e proprietร  tipici del classico oggetto XMLHttpRequest. Questi sono:

  • readyState
  • status
  • statusText
  • responseXML e/o responseText (a seconda che la chiamata restituisca dati sotto forma di XML o testo)
  • setRequestHeader(name, value)
  • getAllResponseHeaders()
  • getResponseHeader()
  • statusCode()
  • abort()

Nella lezione successiva vedremo come scrivere meno codice utilizzando i metodi .get(), .post() e .load().

Pubblicitร 
Massimiliano Bossi
Massimiliano Bossi
Stregato dalla rete sin dai tempi delle BBS e dei modem a 2.400 baud, ho avuto la fortuna di poter trasformare la mia passione in un lavoro (nonostante una Laurea in Giurisprudenza). Adoro scrivere codice e mi occupo quotidianamente di comunicazione, design e nuovi media digitali. Orgogliosamente "nerd" sono il fondatore di MRW.it (per il quale ho scritto centinaia di articoli) e di una nota Web-Agency (dove seguo in prima persona progetti digitali per numerosi clienti sia in Italia che all'estero).