Sommario
< Home
Stampa

AJAX

Introduzione ad AJAX

AJAX è la tecnologia che utilizza Javascript, nel browser, per comunicare con servizi Internet, senza ricaricare la pagina. Grazie ad AJAX la pagina web dialoga col mondo, e si comporta quindi come una applicazione connessa ad Internet. Grazie ad AJAX le applicazioni, composte da una sola pagina HTML, i suoi CSS e soprattutto Javascript, vengono chiamate anche SPA (Single Page Applications), e costituiscono oggi la maggior parte delle applicazioni web moderne, dove ad una applicazione remota (server) che contiene dati ed informazioni, corrisponde una applicazione locale (client) che gira nel browser e li elabora per mostrargli all’utente.

Un esempio famoso di applicazione SPA è Gmail, una pagina web che consente agli utenti registrati di leggere e scrivere le email restando sempre connessi ad una sola pagina web. Lo stesso vale per i social, l’home banking, i servizi di streaming (Netflix, ecc.), i videogiochi online, i programmi da ufficio e di grafica.

Grazie ad AJAX , Javascript diventa quindi in grado di sostituire la maggior parte delle applicazioni desktop e grazie a questa tecnologia vengono abbattute le barriere che esistono tra un pc, un tablet ed uno smartphone in termini di potenza di calcolo ed operazioni possibili.

Protocollo HTTP

Prima di vedere come funziona AJAX bisogna comprendere come funziona il protocollo HTTP.

Questo protocollo prevede una comunicazione tra un client (cioè la nostra applicazione Javascript) ed un server (il web service) e funziona tramite l’invio di una richiesta HTTP (Http Request) e la ricezione di una risposta HTTP (Http Response). 

Esso ha le seguenti caratteristiche distintive:

– invia esclusivamente contenuti testuali: ogni altro tipo di formato (immagini, audio, video) viene codificato in testo;

– è una connessione punto-punto: solo due sono i nodi (host) coinvolti;

– prevede una architettura di rete dove un nodo ha il ruolo di client e l’altra il ruolo di server. Il client ha un ruolo attivo: è la macchina che origina la richiesta verso il server, e ne attende la risposta. Il server è invece in attesa (passiva) di richieste dai client: è costituito da una applicazione opportunamente creata che riceve le chiamate ed elabora le risposte.

http è senza sessione. Due connessioni consecutive e/o contemporanee dallo stesso client sono viste dal server come connessioni da client differenti.

– è opzionalmente previsto uno strato di sicurezza tramite protocollo TLS: combinati insieme danno origine al protocollo https.

HTTP Request

La Request comprende 3 parti:

– una intestazione iniziale, che contiene la URL e il metodo della chiamata. In caso di richiesta dati questo metodo si chiama GET. Un altro metodo molto usato è POST, per inviare dati.

– l’header della chiamata: contiene delle coppie chiave-valore che contengono informazioni di servizio della chiamata (es. autenticazione, formato dei dati, ecc.)

– il body della chiamata: viene usato solo nella POST, e contiene i dati da inviare.

Cosa è la URL

La URL (Uniform Resource Locator) rappresenta in una stringa di testo che server per identificare in modo univoco le risorse richieste.

La URL identifica il protocollo (http, https), il server (cioè il nome della macchina, comprensiva di dominio e sottodominio), la porta (non obbligatorio indicarla se 80), il path della risorsa (identificata come un filesystem virtuale, non è obbligatorio e dipende dalla configurazione del server) ed eventuali richieste aggiuntive opzionali sulla risorsa stessa (detta query string, non obbligatoria nemmeno questa). 

Qui la struttura della stringa: 

http[s]://[thirdleveldomain.]secondlevel.firstleveldomain[:port]/[path/to/resource][?ke1=value1][&key2=value2]...

Le parti tra parentesi quadre sono opzionali

Qui qualche esempio di url con tutti gli elementi

http://www.myserver.org/path/to/resource.html?p1=1&p2=ciao
https://www.google.com
https://cipiaceinfo.it/docs/programmazione/javascript/ajax

HTTP Response

Una volta che il server elabora la request, prepara la Response, che contiene 3 parti:

– l’intestazione con status con un codice (alcuni codici sono 200 OK, 401 non autorizzato, 404 non trovato, 500 errore, vedremo poi altri codici);

– l’header della risposta: contiene delle coppie chiave-valore che contengono informazioni di servizio (es., indica il formato dei dati inviati, ecc.)

– il body della risposta con i contenuti inviati.

Fetch

La chiamata HTTP richiede un certo tempo: la richiesta al server, l’elaborazione lato server, la ricezione della risposta. Tutto questo potrebbe tenere fermo il programma Javascript, bloccando quindi la pagina web. Per questa ragione si usa la programmazione asincrona: si invia la request e si predispone una funzione da eseguire una volta ricevuta la risposta (detta callback). La chiamata effettiva sarà svolta da un thread secondario, che aggiungerà la callback alla coda di esecuzione una volta arrivata la risposta. La callback sarà quindi eseguita quando Javascript tornerà pronto.

La funzione che esegue tutto questo si chiama fetch (ed è compresa nell’oggetto Window, quindi nel BOM). Qui graficamente viene mostrato lo schema generale di funzionamento:

Quel che deve fare il programmatore è richiamare fetch con i parametri della richiesta (url, e quando necessari anche header e body). Nella sua struttura più semplice, ovvero una richiesta di dati al server, è necessaria solo la URL e si usa il metodo GET, che come detto serve nella maggior parte dei casi per ricevere dati.

La fetch viene eseguita in modalità asincrona: la richiesta viene eseguita da un thread secondario che viene istruito quindi sia sul tipo di richiesta da fare (la URL), che col nome della callback da inserire nella coda di esecuzione una volta ricevuta la risposta.

GET

Qui un esempio di chiamata fetch:

fetch("https://dummyjson.com/c/d3f5-e907-4ca1-afa6")
       .then(response => response.json())
       .then(data => console.log(data));

La console stamperà questo:

[
  {
    "firstName": "Mario",
    "lastName": "Rossi"
  },
  {
    "firstName": "Marta",
    "lastName": "Bianchi"
  }
]

Analizziamo questo codice.

1) La fetch riceve come argomento la sola URL, la chiamata GET è di default. La fetch genera un oggetto chiamato promise. Questo oggetto prevede un metodo then() che riceve come argomento la callback da eseguire.

2) A questo punto parte il thread secondario che effettua la richiesta, ed attende la risposta, senza bloccare lo script Javascript.

3) Appena ricevuta la risposta il thread secondario aggiunge alla coda di esecuzione la callback indicata nella then().

4) La risposta come abbiamo visto sopra non è composta solo dai dati ma anche da altre informazioni. I dati contenuti nel body della risposta vanno convertiti, in questo caso in formato JSON. Anche questa operazione è asincrona[2], e quindi è necessaria una seconda funzione response.json() che genera una nuova promise. Per questo c’è un secondo “then”, che semplicemente indica la callback da eseguire con i dati ormai ricevuti.[3]

POST

La chiamata POST serve per inviare una richiesta HTTP in cui vengono inviati dei dati al server.

Questo può essere necessario per due ragioni:

– quando il client vuole richiedere informazioni ma le risorse di cui ha bisogno non possono essere inserite nella URL (perché non è possibile inserirle nella URL per ragioni di spazio o riservatezza o anche semplice uniformità).

– quando il client vuole inviare dei dati al server.

La struttura di una chiamata post sarà con la seguente sintassi:

fetch(url, {
   method: "POST",
   headers: {
   	"key": "value",
        ...
   },
   body: content // deve essere una stringa
})
	.then(response => response.json())
	.then(data => ... istruzioni da eseguire);

Riassunto

Fetch è la funzione che permette di comunicare tra l’applicazione Javascript e i servizi su Internet che forniscono e ricevono dati. La richiesta prevede una URL, un metodo, degli headers e un body. In base al metodo alcuni parametri sono obbligatori, altri sono facoltativi o vietati:

  • Con GET si deve inviare la URL, opzionalmente anche gli headers, ma il body non è consentito. Si usa in generale per richiedere una risorsa identificata dalla URL.
  • Con POST invece si inviano la URL, opzionalmente gli headers, ma è previsto l’invio anche del body. Si usa in generale quando dall’applicazione si vogliono inviare dei dati, ad esempio inseriti dall’utente. Non bisogna fare confusione però: la POST si può utilizzare anche quando si richiede una risorsa, ma siccome la richiesta può essere basata su una struttura dati complessa, allora è comunque necessario inviare dei dati.

Gli headers sono delle coppie nome-valore che servono per mandare al server un insieme di informazioni ad esempio sul formato dati e sulla sicurezza. Gli headers sono fondamentali anche per gestire, in molti casi, anche la sicurezza, per esempio inviando un codice di sicurezza per autenticare il client.

Il body della richiesta contiene i dati da inviare al server. In queste lezioni useremo solo il formato JSON sia per i dati inviati che per quelli ricevuti, ma si ricorda che sul web sono presenti molti altri formati, come ad esempio XML.

La fetch è una funzione asincrona, che crea un oggetto promise, che offre un metodo then(). A questo metodo bisogna passare una prima callback che trasforma la risposta in un oggetto Javascript e che è a sua volta una promise a cui colleghiamo una ultima callback in cui i dati sono pronti ed usabili per i nostri scopi.


[1] Asyncronous Javascript and XML (inizialmente si usava solo con il formato XML).

[2] la conversione è asincrona perché può richiedere un tempo significativo che potrebbe bloccare la richiesta.

[3] questo doppio passaggio della fetch potrebbe essere gestito con una sola promise. Nelle prossime lezioni scriveremo un metodo per gestire tutto con una sola promise.