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).