JQuery: AJAX sì, fatica no!

Come dovreste ben sapere cari lettori di CoseNonJaviste, AJAX è l’acronimo di Asynchronous JavaScript and XML ed è ad oggi la tecnica più utilizzata per sviluppare applicazioni web interattive, altrimenti dette RIA (Rich Internet Application). Il concetto che sta alla base di una chiamata AJAX è quello di poter scambiare dati tra client e server senza ricaricare la pagina: lo scambio avviene in background tramite una chiamata asincrona dei dati di solito utilizzando l’oggetto XMLHttpRequest. E questo scambio di dati è realizzato, come si può intuire dall’acronimo, mediante funzioni scritte con il linguaggio JavaScript.
Ajax può essere difficile da implementare, a meno che non utilizziate JQuery, infatti è anche grazie alla possibilità di realizzare in maniera semplice delle complesse chiamate di questo tipo, che jQuery è un framework così diffuso. 😉

In passato ci siamo già occupati di AJAX e jQuery, tuttavia si è trattato solo di una breve introduzione che in questo articolo affronteremo in maniera più approfondita. In particolare vedremo:

 

LOAD in progress…

Iniziamo questo viaggio con il primo protagonista, il metodo load (che è cosa diversa dall’ evento omonimo). La sintassi è la seguente:

$("#selettore").load(url,[data],[complete])

Questo metodo permette di caricare dei dati dal server e di metterli direttamente dentro l’elemento selezionato (cioè l’elemento con: id="selettore"). I parametri passati sono classificabili come segue:

  • url: URL verso il quale effettuare la richiesta;
  • data : i dati inviati al server. Si può inserire un oggetto in formato chiave/valore (JSON) o come una query string.
    Quando è utilizzata una query string i dati sono passati tramite il metodo GET, se invece si usa il formato chiave/valore allora il metodo utilizzato è il POST;
  • complete(response,status,XMLHttpRequest): è una callback da eseguire al completamento della chiamata, anche se non ha successo. Ha tre parametri: la risposta, lo stato e l’oggetto XMLHttpRequest, tuttavia può anche essere utilizzata senza parametri se questi non servono.

I parametri data e complete sono facoltativi, mentre url è richiesto sempre.

Vediamo qualche semplice esempio:

$('#risultato').load('prova.html');

In questo caso viene caricato il contenuto della pagina prova.html all’interno dell’elemento con id="risultato". Se necessario si può specificare dei dati da passare al server, come nel caso che segue:

$('#risultato').load('prova.php', 'q=0&qq=1&qqq=2');

E cio’ che verrà caricato sarà l’HTML generato dallo script prova.php. Mentre nel prossimo caso, vediamo una callback da eseguire al completamento della chiamata:

$('#risultato').load('prova.html', function() {
    alert('Caricamento completato.');
});

Una funzionalità ulteriore del metodo load è di poter caricare anche porzioni della risorsa, ovvero elementi particolari della pagina prova.html.
Ad esempio, se volessimo caricare solamente l’elemento con id="recupera" ed ignorare tutto il resto del documento, basterà fare:

$('#risultato').load('test.html #recupera');

Se vi ricordate avevamo parlato del Metod chaining, pertanto nel caso di caricamento con attesa, in effetti il metodo load talvolta puo’ risultare un po’ lento, possiamo provare una finezza come la seguente:

$('#risultato').html('Loading...').load('prova.html');

Prima di cambiare argomento e passare ad altro, ecco un esempio riepilogativo.

warningPer motivi di sicurezza il contenuto caricato dalla funzione load deve essere archiviato nello stesso dominio della pagina web dal quale viene lo script. Se dovete accedere a contenuto ospitato in un dominio diverso, occorre procedere in altro modo. In particolare se il server di terze parti può fornire dati JSONP, considerare di usare ad esempio la funzione getJSON, che vedremo più avanti.

 

$.ajax lo stakanovista

jQuery mette a disposizione diversi comandi per l’interazione con AJAX. Tuttavia la funzione principale per inviare richieste di questo tipo è il metodo statico $.ajax, la cui definizione è la seguente:

$.ajax({url, [settings]})

La funzione permette di effettuare una chiamata AJAX e di personalizzarla con molti parametri, i quali vengono passati tramite notazione JSON (tra l’altro questo permette di definire un unico oggetto JSON così da poterlo passare al metodo, qualora possa risultare comodo). I suddetti parametri sono classificabili secondo le seguenti tipologie:

  • url: url della risorsa;
  • settings:
    • dati da passare;
    • funzione da eseguire al termine della chiamata.

Scendiamo nel dettaglio e vediamo una panoramica dei principali:

  • url : URL della risorsa alla quale viene inviata la richiesta;
  • type : il tipo di richiesta HTTP da effettuare. Accetta GET o POST ( il valore di default è: 'GET');
  • data : che può essere un oggetto del tipo {chiave : valore, chiave2 : valore}, oppure una stringa del tipo "chiave=valore&chiave2=valore2" contenente dei dati da inviare al server;
  • 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";
  • success(data, textStatus, XMLHTTPRequest) : funzione che verrà eseguita al successo della chiamata. I tre parametri sono, rispettivamente, l’oggetto della richiesta, lo stato e la descrizione testuale dell’errore rilevato;
  • error(XMLHTTPRequest, textStatus, errorThrown) : funzione che verrà eseguita in caso di errore nell’effettuare la chiamata. Un tipico esempio è dato dall’impossibilità di accedere alla risorsa remota perchè inesistente o, comunque, non accessibile;
  • complete(XMLHTTPRequest, settings) : Consente di specificare una funzione che verrà eseguita al termine della chiamata indipendentemente che abbia dato successo o errore; è eseguita dopo success o error;
  • beforeSend(XMLHTTPRequest, settings) : Callback da eseguire prima che la richiesta sia inviata. I due parametri sono l’oggetto della richiesta e una stringa contenente lo stato della richiesta;
  • timeout : Tempo in millisecondi dopo i quali la richiesta viene considerata scaduta;
  • async : definisce se la chiamata deve essere asincrona (true) o sincrona (false), nel cui caso bloccherà la pagina fino alla fine della chiamata (il valore di default è: true);
  • cache : se impostato su false forza la il browser a ricaricare ogni volta i dati del server anche se non sono cambiati (il valore di default è: true);
  • contentType : il tipo di contenuto inviato al server (il valore di default è: "application/x-www-form-urlencoded");
  • global : global Permette di disabilitare il fatto che la chiamata sia raccolta dagli handler globali, che vedremo più avanti, come ad esempio $.ajaxStart (il valore di default è: true);
  • ifModified : permette che la richiesta sia considerata conclusa con successo (eventi success e ajaxSuccess) solo se i dati restituiti sono diversi da quelli ricavati da una precedente chiamata dello stesso tipo (il valore di default è: false);
  • jsonp : Quando si effettuano chiamate JSONP, si suppone che il nome della funzione di callback sia proprio callback. Se il servizio utilizzato richiede un nome diverso, è possibile ridefinirlo. Così con {jsonp:'onJsonPLoad'} verrà aggiunta alla stringa passata al server "onJsonPLoad=?";
  • username : nome utente se richiesto dal server;
  • password : password se richiesta dal server.

Di seguito potete vedere una tipica chiamata AJAX, che puo’ essere testata a questa pagina e come potete notare, se la chiamata ha successo i dati verranno inseriti all’interno di specifici elementi DOM, altrimenti verrà mostrato un messaggio di errore.

$.ajax({
  url:"richiesta.php",
  type: "GET",
  data: { id: 1234},
  success:function(result){
     $("div#risposta").html(result);
  },
  error: function(richiesta,stato,errori){
     $("div#risposta").html("<strong>Chiamata fallita:</strong>"+stato+" "+errori);
  }
});

warning$.ajax è la funzione principe in jQuery, infatti tutte le altre funzioni AJAX di questo framework, non sono altro che wrapper di questo metodo.

 

Spesso si desidera impostare dei valori di default sulle opzioni per più chiamate AJAX. jQuery ci viene per questo incontro con il metodo:

$.ajaxSetup(options)

Il metodo prende come parametri gli stessi enunciati per $.ajax() i quali in questo caso saranno le impostazioni predefinite comuni per la pagina. Vediamo quindi come si può impostare lo stesso URL e l’utilizzo del metodo POST per tutte le nostre chiamate AJAX:

$.ajaxSetup({
   url: "target.php",
   type: "POST"
});

Non serve quindi che sulle singole chiamate sia specificato l’url, verrà presa infatti sempre la pagina target.php :

$.ajax({
   data: {id: 1234}
});

Ovviamente si può sovrascrivere questo settaggio globale inserendo il parametro url nel metodo $.ajax. Stesso discorso per quanto riguarda il tipo del metodo HTTP.
Per raffreddare i bollenti spiriti, c’è da dire che non è possibile definire tutte le impostazioni mediante $.ajaxSetup: le funzioni di callback come error, complete e success per esempio rientrano in questa categoria. Tuttavia si puo’ bypassare la limitazione adottando per queste callback una gestione con eventi globali di AJAX, che verranno descritti nel successivo paragrafo.

 

l’orizzonte degli EVENTI globali

Per comprendere il modo in cui jQuery gestisce AJAX bisogna introdurre il concetto degli eventi AJAX. Questi sono una serie di eventi che possono essere gestiti in qualsiasi momento desideriate effettuare una elaborazione ulteriore, per esempio aggiungere un messaggio di caricamento all’inizio della richiesta e rimuoverlo al termine. Oppure gestire tutti gli errori che potrebbero verificarsi…
Per prima cosa possiamo dire che tali eventi possono essere divisi in due famiglie:

  • eventi locali
  • eventi globali

Gli eventi locali si applicano solo alle singole richieste AJAX e vengono gestiti come callback, proprio come abbiamo visto per le callback della funzione $.ajax (difatti di eventi locali si tratta…).
Gli eventi globali invece sono gli eventi generati da tutte le chiamate Ajax e vengono trasmessi a tutti i gestori in ascolto. Forniscono un modo utile per implementare funzionalità che si devono applicare a tutte le richieste. Per esempio se volessimo visualizzare i messaggi di errore in un apposito elemento <div id="msg">:

$("#msg").ajaxError(function(event, request, settings){
   $(this).html("Error requesting page: " + settings.url );
});

Ogni qualvolta che una qualsiasi chiamata AJAX dalla pagina genera un errore, verrà chiamato questo gestore appena definito.
Vediamo di seguito un rapido elenco degli eventi globali che è possibile catturare:

  • ajaxStart: attivato quando una chiamata Ajax ha inizio e nessun’altra è in esecuzione;
  • ajaxSend: attivato prima che una chiamata cominci (uguale all’evento locale beforeSend, ma globale);
  • ajaxSuccess: come success, ma globale;
  • ajaxError: come error, ma globale;
  • ajaxComplete: come complete, ma globale;
  • ajaxStop: attivato quando non ci sono più richieste Ajax in attesa di essere processate.

Di seguito vediamo un esempio d’uso delle funzioni ajaxStart e ajaxStop:

$("#main").ajaxStart(function () {
    $("#messaggio").text("caricamento…");
}).ajaxStop(function () {
   $("#messaggio").text("");
});

Prendiamo spunto dall’esempio precedente e vediamo questa versione con la presenza di eventi globali.

 

Scorciatorie

Certo abbiamo visto tutto quello che serve per realizzare una chiamata AJAX, tuttavia jQuery ci fornisce anche delle “scorciatoie” che realizzano particolari chiamate AJAX in modo ancora più veloce e semplificato (come abbiamo detto non sono che wrapper di $.ajax() ).
I primi due metodi, $.get() e $.post(), sono molto utili e altrettanto semplici da utilizzare. Permettono, rispettivamente, di eseguire rispettivamente una richiesta HTTP di tipo GET e una richiesta di tipo POST. In pratica sono la scorciatoia di $.ajax con impostato il parametro type a 'GET' o 'POST'.
I parametri sono gli stessi per i due metodi:

  • url: URL verso il quale effettuare la richiesta, è l’unico parametro obbligatorio, gli altri sono facoltativi.
  • data: dati inviati al server. Si può inserire un oggetto o una stringa.
  • callback(data,status,xhr): callback da eseguire al successo della chiamata.
  • dataType: tipo di dato che ci si aspetta dal server. Di default jQuery prova a “dedurre” da solo questo valore.

Qualora si abbia la necessità di caricare dei dati particolari, come JSON o un file Javascript, allora ci sono dei metodi appositi (entrambi utilizzano il metodo GET).
E’ importante sottolineare prima di procedere oltre, che la funzione di callback viene eseguita solo quando tutto è perfetto, quindi, a meno che non stiate usando un gestore di evento globale, non saprete mai se una chiamata ha esito negativo.
Vediamo ora alcuni esempi per spiegare meglio il loro utilizzo:

$.get("ajax/utenti.php");

Con questo codice ci limitiamo ad effettuare una chiamata ad un file senza passare dati ne pretendere dei dati in ritorno.

$.get("ajax/utenti.php", {nome:"Mario",cognome:"Rossi"});

Con quest’altro codice effettuiamo la chiamata passando dei dati senza richiedere alcuna risposta di ritorno.

$.get("utenti.php", {nome:"Mario",cognome:"Rossi"},
  function(data) {
    $("#risultato").html(data);
 });

Con questo codice, infine, richiediamo anche una risposta che viene inserita nell’elemento HTML con id="risultato" (esempio).
Chiaramente l’uso  della chiamata con $.post() sarebbe stata grossomodo identica.
Per caricare dei dati JSON esiste invece la scorciatoia $.getJSON(). I parametri passati sono gli stessi della chiamata $.get() (a parte il dataType che ovviamente è "json" ). I dati sono ritornati parserizzati tramite $.parseJSON().
La sintassi di questo metodo è la seguente:

$.getJSON(URL, function(oggettoJSON) { // parsing });

Ad esempio:

$.getJSON('test.json', function(json) {
    alert("buon giorno mi chiamo:" json.nome+ " " json.cognome);
});

Nel caso di URL verso domini diversi dal nostro, è di fondamentale importanza che il file JSON remoto sia servito come JSONP, poichè i browser per impostazione predefinita sono vincolati alla regola secondo cui una richiesta AJAX debba avere luogo sullo stesso dominio (esempio con il metodo in azione):

var apiURL = 'https://api.twitter.com/1/users/show.json?screen_name=cosenonjaviste&callback=?';

$.getJSON(apiURL, function(data) {
   var followers = data.followers_count;
   console.log(followers);
});

E’ possibile anche caricare un file Javascript, abbiamo infatti a disposizione il metodo $.getScript(). La cui sintassi è:

$.getScript( url [, callback(script, status, xhr)] );

Il file è eseguito al termine della chiamata e lo stesso file è ritornato nella callback, che viene eseguita se la richiesta ha successo ( link per test ):

    $.getScript("script.js", function(){
      alert("Script caricato ed eseguito.");
    });

 

Inviare dati da form

Adesso vediamo un metodo che permette di serializzare i dati all’interno di una form con: serialize().
Questo metodo serve per creare una stringa in formato URL operando sugli elementi della form (il formato query string per intenderci, cioè quello contenente il nome e il valore del campo separati dal simbolo & ).
Vediamo qui un semplice esempio:

<form>
 <input type="text" name="nome" />
 <input type="text" name="cognome" />
 <input type="button" value="Submit" />
</form>

Il metodo serialize() permette di recuperare tutti quei dati presenti nella form con un attributo name associato, siano essi textbox, textarea, select, etc. Senza effettuare manualmente il recupero uno ad uno.

$('form').submit(function() {
  console.log($(this).serialize());  //nome=Lemmy&cognome=Kilmister
  return false;
});

Se si preferisce invece serializzare i dati in formato JSON…Non c’è da preoccuparsi! Esiste infatti anche il metodo serializeArray(), che ha lo stesso modo d’uso del precedente, ma a differenza di questo restituisce un array di oggetti pronti per essere codificati come stringhe JSON.
Facendo riferimento all’esempio precedente, al posto della query string, avremmo il seguente:

[{
  nome: "Lemmy",
  cognome: "Kilmister"
}]

Per vedere entrambe le funzioni in azione, ecco un esempio.

Riferimenti

Per una visione più completa di tutte le funzionalità offerte da jQuery in ambito AJAX vi rimando, ovviamente, alla documentazione ufficiale. E per finire eccovi una lista di link di approfondimenti e riferimenti su jQuery & AJAX:

Gianni Amendola

Sono laureato in Ingegneria Informatica e lavoro dal 2008 come sviluppatore Java presso OmniaGroup. Sviluppo principalmente applicazioni web soprattutto su piattaforme alternative come ad esempio lo stack JSF+Spring+Hibernate (o altri ORM) oppure lo stack JavaScript(JQuery o ExtJS)+Spring+Hibernate su Tomcat, o sui principali AS (WebSphere,Weblogic,Glassfish, Jboss). Nei ritagli di tempo mi diletto a programmare su piattaforma Android e con altri linguaggi, quali ad esempio Python. LinkedIn profile

  • Pingback: Questions About Jquery Ajax | Top Apprentice Blog()

  • Pingback: Questions About Jquery | Top Apprentice Blog()

  • bellisima guida
    chiara anche per me che questo argomento è sempre stato ostico.
    Per caso ho trovato un errore nella parte del metodo load dove passa al server anche la query string, manca il punto interogativo.
    ciao e ancora tantissimi complimenti

    • oltre

      comincio a pensare che non è ostico solo per me ma per tutti. Sto schifo di jquery sono praticamente incomprensibili, il codice è difficile da leggere e quando si scrive qualcosa si procede molto lentamente. Ci perdo giorni e giorni ma ci capisco poco. 5000 parentesi che non si quando si devono chiudere , errori a non finire e una noia mortale. W il semplice html col vecchio javascript e il php (quest’ultimo senza classi)

  • Ariel

    Quale versione di jQuery hai usato per scrivere questo codice?

  • Marco D’Elia

    si può fare una cosa del genere$.ajax({
    02 url:”richiesta.php”,
    03 type: “GET”,
    04 data: { id: 1234},
    05 success:function(result){
    06 $(“div#risposta”).html(result);
    07 },
    $.ajax({
    09 url:”richiesta2.php”,
    10 type: “GET”,
    11 data: { id: 1234},
    12 success:function(result){
    13 $(“div#risposta2”).html(result);
    14 },

  • Marcello Kad Cadoni

    Ci sentiamo quando devi combattere con l’aspetto seo, penso che l’entusiasmo ti cali un bel po. Impazzire con localstorage, friendly url, indicizzazione e gestione del flusso asincrono per ricavare piu’ informazioni da diverse fonti

  • CORIGLIANO Informa

    Articolo molto interessante
    —————————————————-
    CORIGLIANO Informa