Categorie
Javascript Programmazione

{JS} API di comunicazione: AJAX

Le API di comunicazione

Una delle limitazioni delle pagine Web di qualche anno fa era l’impossibilità di interagire direttamente con il server ed aggiornare i contenuti senza dover ricaricare la pagina; queste limitazioni sono state superate grazie a delle API standard che consentono l’interazione con il server usando JavaScript.

AJAX

AJAX sta per A sincrono J avaScript e X ML . E’ possibile utilizzare la tecnologia AJAX mediante l’uso dell’oggetto built-in XMLHttpRequest che ci consente di comunicare con i server. 
Potremo, infatti, inviare e ricevere informazioni in vari formati (JSON, XML, HTML e file di testo) consentendoci di scambiare informazioni tra la web-page e il server.

Potremo quindi:

  • Invia richieste al server senza ricaricare la pagina
  • Riceve e lavora i dati dal server


La natura di AJAX è “asincrona”, il che significa che può comunicare con il server, scambiare dati e aggiornare parti della pagina senza doverla ricaricare.

Note: In informatica "built-in" sta ad indicare un componente incorporato ed eseguito automaticamente.

Per comunicare con il server dovremo quindi dichiarare, ad ogni interrogazione, una nuova richiesta.

Per effettuare una nuova richiesta HTTP al server è necessario creare una nuova istanza di un oggetto che possiede le funzionalità necessarie. Il nostro oggetto è l’oggetto XMLHttpRequest.

var nuovaRichiesa = new XMLHttpRequest();

Essendo la natura di AJAX asincrona dovremo contenere tutte le istruzioni in una funzione-con-nome in modo da poterla richiamare al momento del verificarsi di un evento.

function compila(){
var nuovaRichiesa = new XMLHttpRequest();
...

L’adopereremo in questo modo:

element.onclick = compila();
//oppure
window.onload = compila();

Questo approccio ci consente di recuperare informazioni dal server di seguito ad un evento, che potrebbe anche essere un evento d’interfaccia come “load” e di aggiornare porzioni singole della nostra pagina web in maniera asincrona.

L’oggetto XMLHttpRequest 

La generazione di una nuova istanza dell’oggetto XMLHttpRequest (“nuova richiesta al server”) associa le proprietà ed i metodi dell’oggetto XMLHttpRequest alla nuova istanza.

Le proprietà ed i metodi ereditati dall’istanza sono divisibili in due categorie:

  • proprietà e metodi per la gestione delle richieste
  • proprietà e metodi per la gestione delle risposte

Per la gestione della richiesta

⭐️ .open()apre connessione con il server
⭐️.send()invia la richiesta al server
⭐️.setRequestHeader()impostare il tipo MIME della richiesta

.open()

Contrariamente al suo nome., il metodo .open(), non apre di fatto la connessione ma la imposta indicandone il tipo, il file da richiedere ed il tipo di richiesta.

Prevede quindi 3 argomenti:


argomento
GET o POST che identificano il tipo di richiesta Inserire il metodo tutto maiuscolo secondo lo standard HTTP, altrimenti alcuni browser (come Firefox) potrebbero non elaborare la richiesta.

argomento
L’url del file che vogliamo richiamareCome funzionalità di sicurezza, per impostazione predefinita non puoi chiamare URL su domini di terze parti altrimenti sarà mostrato l’errore “permesso negato” 

argomento
imposta se la richiesta è asincronaIl valore true=asincrona mentre il valore false=sincrona.
Se la richiesta è asincrona il terzo parametro può essere omesso.
...
nuovaRichiesta.open('GET','file.json', true); 
...
GET & POST

Sia il metodo GET che POST sono utilizzati per inviare richieste dal client ad un server.

Quali sono quindi le differenze sostanziali tra POST e GET:

  • GET trasporta il parametro di richiesta mostrandolo nella stringa URL, detta QueryString;
  • POST trasporta il parametro di richiesta nel corpo stesso della richiesta, nascondendolo e rendendolo più sicuro.
Query String

Abbiamo visto che esistono due tipi di richieste, GET e POST, che è possibile effettuare verso un server; per semplificare al massimo, il risultato sarà lo stesso per entrambe ma, la prima è visibile (nell’url) e la seconda è nascosta (nel corpo della richiesta).

Generalmente se il tipo di richiesta è semplice, come la richiesta ed il ritorno statico di un file specifico (.json, xml ecc.) presente sul server
è possibile utilizzare il metodo GET.

Esistono però richieste che necessitano di una elaborazione da parte del server prima che sia inviata una risposta coerente;

Questo tipo di richiesta, detta richiesta mediante queryString o stringa di ricerca, punta sempre ad un url specifico ma necessita anche di paramenti con cui si potrà formulare la domanda al server.


In informatica una query-string o stringa di ricerca è la parte di un URL che contiene dei dati da passare in input ad un programma. L’URL conterrà l’indirizzo di un server ed il percorso nel suo file system per arrivare alla directory nella quale è presente l’eseguibile che si occupera dell’elaborazione.

In una richieste che può riguardare la “meccanica” del sito stesso come una semplice ricerca:

../search?articoli=motocicli

potremo continuare ad utilizzare il metodo GET.

Qualora la richiesta al server contenga una queryString con informazioni sensibili

../?codiceFiscale=SCLLCU85E10L352Y&cartaDiCredito=5489234567890012

ed in generale informazioni riservate che sono state da prima inserite dall’utente sulla nostra app/sito mediante campi di input, è consigliabile l’utilizzo del metodo POST.

Il meccanismo di richiesta mediante query è molto utilizzato nelle API di thirty-part di tipo RESTfull e lo esamineremo nel dettaglio in una sezione dedicata alle API di terze parti

.send()

Il metodo send() si occupa di spedire di fatto la richiesta al server ed eventualmente può contenere o non contenere dati o parametri.

Se l’obbiettivo è semplicemente quello di recuperare il contenuto di un file è possibile non aggiungere alcun paramento.

nuovaRichiesta.open('GET','file.json', true); 
nuovaRichiesta.send();
...

Qualora la richiesta contenga l’esigenza che siano elaborati dei dati il metodo send() potrà contenere paramentri.

var queryString ='?codiceFiscale=SCLLCU85E10L352Y&cartaDiCredito=5489234567890012';

nuovaRichiesta.open('POST', 'https://www.server.it/utenti/', true);
nuovaRichiesta.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
nuovaRichiesta.send(queryString);
...

.setRequestHeader()

Con il metodo .setRequestHader() impostiamo il MIMEType del dato che ci apprestiamo ad inviare.

nuovaRichiesta.open('GET', file.json, true);
nuovaRichiesta.setRequestHeader('Content-Type', 'application/json');
MIME-Type

“MIME Type” nasce dalla concatenazione di “MIME” e “Content-Type”, comunemente e forse erroneamente usato nell’ambito dello sviluppo di pagine web per indicare il tipo di contenuto e di dati che compone un determinato file.

Di seguito i più comuni e frequenti MIME-Type utilizzati.

.css‘Content-Type’ ,‘text/css’
.csv‘Content-Type’ ,‘text/csv’
.htm .html‘Content-Type’ ,‘text/html’
.json‘Content-Type’ ,‘application/json’
.pdf‘Content-Type’ ,‘application/pdf’
.php‘Content-Type’ ,‘application/x-httpd-php’
.txt‘Content-Type’ ,‘text/plain’
.xhtml‘Content-Type’ ,‘application/xhtml+xml’
.xml‘Content-Type’ ,‘application/xml’
moduli web‘Content-Type’ ,‘application/x-www-form-urlencoded’
invio file-dati‘Content-Type’ ,‘multipart/form-data’

Il MIME-Type ‘application/x-www-form-urlencoded‘ è principalmente utilizzato per i moduli web ed essenzialmente per l’invio di dati di tipo “chiave-valore”; questo MIME-Type inoltre si occupa di effettuare la codifica dei relativi segni riservati come l’unione “&” e l’attribuzione “=” (come avviene nelle QueryString);

L’utilizzo più comune è quello di recuperare questi valori “chiave-valore” da un form di una pagina HTML per inviarli tramite una richiesta HTTP ad un file PHP che in fine si occuperà della loro lavorazione/rielaborazione.

multipart/form-data‘, invece, è utilizzato per lo più per l’invio di file-dati al server.

Per la gestione della risposta

⭐️ .onreadystatechangeproprietà in cui definire le azioni da eseguire lo stato della richiesta cambia
⭐️.readyStaterestituisce lo stato della richiesta
⭐️.statusrestituisce il valore di “come” il server ha risposto
.statusTextmessaggio dello status HTTP in stringa. OK per 200Not Found per 404Forbidden per 403 ecc.
.responseTypespecifica il tipo di dati contenuti nella risposta
⭐️.responseTextrestituisce la risposta del server come stringa di testo
.responsecome .responseText
⭐️.responseXMLrestituisce la risposta come un oggetto XMLDocument che può essere attraversato con le funzioni DOM
.timeout specificare un timeout per la richiesta
.onloadproprietà in cui definire l’azione (funzione) da eseguire quando la richiesta è completa
.onerrorproprietà in cui definire l’azione (funzione) da eseguire quando la richiesta non può essere espletata
.onprogressproprietà in cui definire l’azione (funzione con paramento “event”) da eseguire. Viene innescato periodicamente mentre la risposta viene scaricata.
event.loadedquanti bytes sono stati scaricati
event.totalnumero totale di bytes della richiesta

.onreadystatechange

Alla proprietà .onreadystatechange possiamo associare una funzione e definire le azioni da eseguire quando lo stato della richiesta cambia.

Deve essere precisato che una richiesta al server dal momento dell’invio assumerà diversi stati e diversi esiti.

nuovaRichiesa.onreadystatechange = function(){
...
}

All’interno di questa funzione potremo utilizzare altre proprietà specifiche per la gestione di una richiesta che ci aiutano nell’identificare gli stati e gli esiti di quest’ultima.

.readyState

La proprietà può restituire i seguenti valori ed indica lo stato della richiesta:

0richiesta non inizializzata
1richiesta abilitata
2il server ha ricevuto la richiesta
3il server sta processando la richiesta
4il server ha finito di processare la richiesta ed ha ritornato la risposta
.status

La proprietà può restituire i seguenti valori ed indicano gli esiti ovvero “come” il server ha risposto:

200il server ha trovato quanto richiesto e lo sta inviando
404il server non ha trovato quello che cercavamo

Queste due proprietà possono essere utilizzate all’interno della funzione attraverso una istruzione IF per un controllo dello stato della richiesta prima di eseguire determinate azioni.

nuovaRichiesta.onreadystatechange = function(){
if(this.readyState === 4 && this.status === 200){
...
}
}

Il server ha finito di processare la richiesta correttamente (“4”), ha trovato quanto richiesto e lo sta inviando (“200”).

.responseText

La proprietà ritorna la risposta del server

function compila(){
var nuovaRichiesta = new XMLHttpRequest(); 
nuovaRichiesta.open('GET','file.json', true); 
nuovaRichiesta.send(); 

nuovaRichiesta.onreadystatechange = function(){
    if(this.readyState === 4 && this.status === 200 ){
       
 var risultato = JSON.parse(nuovaRichiesta.responseText);

        var nome, cognome, professione, utenteId;
        nome = document.getElementById('nome');
        cognome = document.getElementById('cognome');
        professione = document.getElementById('professione');
        utenteId = document.getElementById('utenteId');

        nome.innerHTML=`${risultato.nome}`;
        cognome.innerHTML=`${risultato.cognome}`;
        professione.innerHTML=`${risultato.professione}`;
        utenteId.innerHTML=`${risultato.id}`;
        
    }
}

Nel riga 9 del codice qui sopra abbiamo dovuto provvedere alla conversione della risposta “.responseText” che contiene il file json mediante “JSON.parse(nuovaRichiesta.responseText);”

A questo punto la funzione compila() è pronta per essere lanciata.

<button onclick="compila();">Compila</button>

Le proprietà del file json convertite in oggetto javascript saranno inserite, in seguito all’evento click sul bottone, all’interno degli appositi campi <span>; di seguito il codice completo HTML+JS, il contenuto del file json e l’esecuzione di questo script.

File index.html

<div>
<p>Nome: <span id="nome"></span></p>
<p>Cognome: <span id="cognome"></span></p>
<p>Professione: <span id="professione"></span></p>
<p>Id Utente: <span id="utenteId"></span></p>
</div>
<div><button onclick="compila();">Compila</button></div>

<script>

function compila(){   
var nuovaRichiesta = new XMLHttpRequest();
nuovaRichiesta.open('POST', 'file.json', true);
nuovaRichiesta.setRequestHeader('Content-Type', 'application/json');
nuovaRichiesta.send();

nuovaRichiesta.onreadystatechange = function(){
    if(this.readyState === 4 && this.status === 200 ){
        var risultato = JSON.parse(nuovaRichiesta.responseText);

        var nome, cognome, professione, utenteId;
        nome = document.getElementById('nome');
        cognome = document.getElementById('cognome');
        professione = document.getElementById('professione');
        utenteId = document.getElementById('utenteId');

        nome.innerHTML=`${risultato.nome}`;
        cognome.innerHTML=`${risultato.cognome}`;
        professione.innerHTML=`${risultato.professione}`;
        utenteId.innerHTML=`${risultato.id}`;
        
    }
}


}
</script>
File file.json
{
 "id": "1",
 "nome": "Lucio",
 "cognome": "Asciolla",
 "professione": "Front-End Web Developer"
}

Richiesta di un file .xml

Rispetto ad un file .json l’approccio con un file.xml risulta differente.
Un file xml è un linguaggio di markup del tutto similare ad HTML.
Per tale motivo potremo sfruttare questa sua proprietà per navigare all’interno dei suo tag/nodi.

index.html
<script>

var        xmlRichiestaHTTP = new XMLHttpRequest();
        xmlRichiestaHTTP.open('GET', 'file.xml', true);
      xmlRichiestaHTTP.send();
        xmlRichiestaHTTP.onreadystatechange = function(){
           if(this.readyState === 4 && this.status === 200){   
                xmlDocument = xmlRichiestaHTTP.responseXML;
 }
}
</script>
file.xml
<?xml version="1.0" encoding="UTF-8" ?>
<persona>    
<firstName>John</firstName>
    <lastName>Smith</lastName>
    <isAlive>true</isAlive>
    <age>18</age>
    <address>
        <streetAddress>21 2nd Street</streetAddress>
        <city>New York</city>
        <state>NY</state>
        <postalCode>10021-3100</postalCode>
    </address>
    <phoneNumbers>
        <type>home</type>
        <number>212 555-1234</number>
    </phoneNumbers>
    <phoneNumbers>
        <type>office</type>
        <number>646 555-4567</number>
    </phoneNumbers>
    <phoneNumbers>
        <type>mobile</type>
        <number>123 456-7890</number>
    </phoneNumbers>
</persona>  

Nel file index.html abbiamo creato una nuova richiesta HTTP al server;
Quel che cambia da quanto visto prima è la tipologia di file richiesto “file.xml”;
Ulteriore differenza rilevabile è l’utilizzo della proprietà .responseXML, per la risposta, che è del tutto similare a .responseText; questa restituirà tutto il contenuto del file xml all’intenro della variabile “xmlDocument”.
Quest’ultima sarà un oggetto simile all’oggetto “document” navigabile con le medesime proprietà.

Il formato XML è stato creato con l’obbiettivo di condividere dati tra applicazione; dobbiamo pensare a xmlDocument come ad un documento nel documento document.

xmlDocument.querySelector('firstName').textContent;

con la proprietà “.textContent” possiamo facilmente recuperare i valori testuali contenuti all’interno dei tag del file xml.

Risorse dal web:
HTTPS://DEVELOPER.MOZILLA.ORG/EN-US/DOCS/WEB/GUIDE/AJAX/GETTING_STARTED#STEP_1_%E2%80%93_HOW_TO_MAKE_AN_HTTP_REQUEST

HTTPS://IT.JAVASCRIPT.INFO/XMLHTTPREQUEST


Tabella di tutti i tipi di MIME nell’ambito web:

HTTPS://DEVELOPER.MOZILLA.ORG/EN-US/DOCS/WEB/HTTP/BASICS_OF_HTTP/MIME_TYPES/COMMON_TYPES

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *