Lezione 3
Ajax ruota intorno all’oggetto XMLHttpRequest che rappresenta l’intermediario tra il codice JavaScript eseguito sul browser e il codice eseguito sul server. Questo oggetto mette a disposizione tutti gli strumenti per creare ed inviare richieste HTTP e ricevere ed analizzare le relative risposte.
let httpReq = new XMLHttpRequest();
httpReq.onreadystatechange = function() {
if (httpReq.readyState == 4 && httpReq.status == 200) {
document.getElementById("myDiv").innerHTML = httpReq.responseText;
}
};
httpReq.open("GET", "/myServerPage", true);
httpReq.send();
let httpReq = new XMLHttpRequest();
httpReq.onreadystatechange = function() {
if (httpReq.readyState == 4) {
switch(httpReq.status) {
case 200:
document.getElementById("myDiv").innerHTML = httpReq.responseText;
break;
case 404:
alert("La pagina indicata non esiste!");
break;
case 500:
alert("Si è verificato un errore sul server!");
break;
default:
alert("Non è possibile elaborare la richiesta (" + httpReq.statusText + ")");
}
}
};
Rispetto a XMLHttpRequest, fetch() ha una sintassi più semplice e meglio integrata nel modello ad oggetti di JavaScript.
L’API prevede una gestione delle chiamate asincrone basata sulle promise.
fetch("http://www.kaleidoscope.it")
.then(response => {
if (response.ok) {
console.log("Contenuto ricevuto");
}
if (response.status >= 100 && response.status < 200) {
console.log("Informazioni per il client");
}
if (response.status >= 300 && response.status < 399) {
console.log("Redirezione");
}
if (response.status >= 400 && response.status < 499) {
console.log("Richiesta errata");
}
if (response.status >= 500 && response.status < 599) {
console.log("Errore sul server");
}
}).catch(error => console.log("Si è verificato un errore!"))
fetch("http://www.kaleidoscope.it/api/articoli", {
method: "post",
headers: new Headers({
"Content-Type": "application/json"
}),
body: JSON.stringify({
titolo: "Un articolo",
autore: "Mario Rossi"
})
})
.then(...)
.catch(...)
Le Promise sono considerate una delle novità più interessanti di JavaScript nella versione ES6+ (ECMAScript 6).
Le Promise sono state concepite per rappresentar operazioni incomplete al momento corrente che saranno però complete in futuro; per questo motivo parliamo di un costrutto adottato nel caso di elaborazioni asincrone e differite.
Data la loro natura le Promise prevedono tre stati differenti:
fulfilled: cioè “soddisfatto”, che si verifica quando un’operazione ha avuto successo
rejected: cioè “respinto”, nel caso del fallimento di un’operazione.
function httpGet(url) {
return new Promise(function(resolve, reject) {
let httpReq = new XMLHttpRequest();
httpReq.onreadystatechange = function() {
let data;
if (httpReq.readyState == 4) {
if (httpReq.status == 200) {
data = JSON.parse(httpReq.responseText);
resolve(data);
} else {
reject(new Error(httpReq.statusText));
}
}
};
httpReq.open("GET", url, true);
httpReq.send();
});
}
httpGet("/utente/123").then(
function(utente) {
console.log("Il server ha restituito l'utente " + utente.nome);
},
function(error) {
console.log("Si è verificato l'errore " + error.message);
}
);
function getUtente() {
return httpGet("/utente/123");
}
function getBlog(utente) {
return httpGet("/blog/" + utente.blogId);
}
function displayBlog(blog) {
displayPostList(blog.posts);
}
function gestisciErrore(error) {
console.log(error.message);
}
getUtente()
.then(getBlog)
.then(displayBlog)
.catch(gestisciErrore);
Attraverso l’uso delle Device Orientation API è possibile capire se il dispositivo mobile è in verticale oppure in orizzontale.
Non solo, ci permette anche di capire il movimento e l’accelerazione di un dispositivo.
Per intercettare i cambi di orientamento del dispositivo dobbiamo usare l’evento DeviceOrientationEvent generato dall’accelerometro.
function handleOrientation() {}
window.addEventListener("deviceorientation", handleOrientation);
L’evento DeviceOrientationEvent contiene le seguenti informazioni:
Absolute è una proprietà booleana, quindi può essere solo true o false.
Se true indica che il sistema di coordinate da considerare è quello terrestre, cioè quello che considera il centro della terra come origine, l’asse X parallelo alla superficie terrestre e orientato verso est, l’asse Y parallelo alla superficie terrestre e orientato verso nord e l’asse Z perpendicolare alla superficie terrestre e orientato verso l’alto.
Se false il sistema di coordinate è basato sul dispositivo stesso, con l’origine coincidente con il centro del dispositivo, l’asse X parallelo allo schermo e orientato verso destra, l’asse Y parallelo allo schermo e orientato verso l’alto e l’asse Z perpendicolare allo schermo e orientato fuori dal dispositivo.
Questo è il sistema di coordinate quando absolute è false
Alpha indica la rotazione del dispositivo intorno all’asse Z con un valore che va da 0 a 360 gradi.
Beta indica lo spostamento intorno all’asse X con un valore che va da -180 a 180 gradi.
Gamma indica indica la rotazione del dispositivo intorno all’asse Y con un valore che va da -90 a 90 gradi.
Per intercettare i dati sul movimento del dispositivo dobbiamo usare l’evento DeviceMotionEvent.
function handleMotion() {}
window.addEventListener("devicemotion", handleMotion);
L’evento DeviceMotionEvent contiene le seguenti informazioni:
Attraverso l’uso delle Geolocation API è possibile capire la posizione attuale del dispositivo, attraverso le coordinate GPS.
Per accedere a tutte queste informazioni, useremo l'oggetto navigator.
La prima cosa da fare per accedere alla posizione corrente dell’utente è verificare il supporto della specifica funzionalità.
function mostraPosizione(posizione) {
console.log("Latitudine: " + posizione.coords.latitude);
console.log("Longitudine: " + posizione.coords.longitude);
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(mostraPosizione);
}
Si possono verificare situazioni in cui, seppure la funzionalità è supportata, per qualche motivo viene generato un errore, magari per problemi di copertura o altro.
Per gestire l'errore:
function mostraPosizione(posizione) {
console.log("Latitudine: " + posizione.coords.latitude);
console.log("Longitudine: " + posizione.coords.longitude);
}
function gestisciErrore(error) {
switch(error.code) {
case error.PERMISSION_DENIED:
console.log("Permesso negato dall'utente");
break;
case error.POSITION_UNAVAILABLE:
console.log("Impossibile determinare la posizione corrente");
break;
case error.TIMEOUT:
console.log("Il rilevamento della posizione impiega troppo tempo");
break;
case error.UNKNOWN_ERROR:
console.log("Si è verificato un errore sconosciuto");
break;
}
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(mostraPosizione, gestisciErrore);
}
Un'altra situazione molto comune può essere quella di osservare la posizione di un utente nel tempo.
Per farlo si usa la funzione watchPosition
let watch;
let options = {
enableHighAccuracy: true,
maximumAge: 10000,
timeout: 2000
};
if (navigator.geolocation) {
watch = navigator.geolocation.watchPosition( mostraPosizione, gestisciErrore, options );
}
Il metodo watchPosition() funziona in maniera del tutto analoga al metodo setInterval() per la gestione dei timer. In maniera altrettanto analoga, se vogliamo interrompere il rilevamento continuo della posizione utilizzeremo il metodo clearWatch() passandogli l’identificatore della watch da eliminare:
navigator.geolocation.clearWatch(watch);
Il mondo mobile ha introdotto anche l'obbligo di dover gestire il touch dei dispositivi.
Per farlo si usano una serie di eventi, in tutto simili agli eventi del mouse.
Gli eventi Touch sono:
window.addEventListener("touchstart", function() {});
window.addEventListener("touchend", function() {});
window.addEventListener("touchmove", function() {});
Con Web Storage potete memorizzare dati localmente sul browser.
A differenza dei cookie, il Web Storage mette a disposizione uno spazio disco, fino a 5MB.
Le informazioni non vengono mai trasferite al server.
WebStorage prevede 2 tipologie di storage, più specificatamente:
Per tutte le altre funzionalità, i due oggetti JavaScript sono identifici.
WebStorage prevede il salvataggio di dati con un meccanismo chiave-valore, un po' come un array associativo.
// SALVO SU LOCAL STORAGE IL PIGRECO SOTTO FORMA DI STRINGA
localStorage.setItem("pigreco", "3.14");
let utente = { nome: "Mario", cognome: "Rossi" };
// CON LA FUNZIONE JSON.stringify CONVERTO UN OGGETTO JSON IN STRINGA
// POI LO SALVO SU SESSION STORAGE
utente = JSON.stringify(utente);
// SALVANDO SU SESSION STORAGE, ALLA CHIUSURA DELLA FINESTRA, IL DATO SCOMPARE
sessionStorage.setItem("utente", utente);
// PER LEGGERE DA LOCAL STORAGE, USO LA FUNZIONE getItem
let piGreco = localStorage.getItem("pigreco");
// CON LA FUNZIONE JSON.parse CONVERTO UNA STRINGA IN OGGETTO JSON
let utente = JSON.parse(sessionStorage.getItem('utente'));
// ELIMINO SOLO IL VALORE CON LA CHIAVE pigreco
localStorage.removeItem("pigreco");
// ELIMINO TUTTI I VALORI PRESENTI
sessionStorage.clear();