JavaScript

Lezione 3

API di Comunicazione

AJAX

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();

La risposta dal server

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 + ")");
        }
    }
};

Fetch API

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!"))

Invio di dati a un server con Fetch API

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

Promise

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:

  • pending: cioè in attesa, che è lo stato iniziale
  • fulfilled: cioè “soddisfatto”, che si verifica quando un’operazione ha avuto successo

  • rejected: cioè “respinto”, nel caso del fallimento di un’operazione.

Un esempio

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);
    }
);

Concatenare le promise

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

Mobile Device API

Device Orientation API

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
  • alpha
  • beta
  • gamma

 

Device Orientation API - Absolute

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

Device Orientation API - Alpha, Beta e Gamma

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.

Device Orientation API

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:

  • acceleration: questa proprietà riporta l’accelerazione espressa in metri per secondo quadrato (m/s2). E' rappresentata da un oggetto con le proprietà x, y, e z rappresentanti rispettivamente l’asse da ovest verso est, l’asse da sud a nord e l’asse perpendicolare alla terra
  • accelerationIncludingGravity: questa proprietà è analoga alla precedente, ma include nell’accelerazione del dispositivo anche l’accelerazione di gravità
  • rotationRate: rappresenta la velocità di rotazione intorno a ciascun asse espresso in gradi al secondo; le sue proprietà alpha, beta e gamma corrispondono a quanto visto a proposito dell’orientamento del dispositivo
  • interval: indica l’intervallo di tempo in millisecondi di rilevazione del movimento da parte dell’hardware del dispositivo

 

Geolocation API

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);
}

Geolocation API

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);
}

Geolocation API

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

Touch API

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:

  • touchstart
  • touchend
  • touchmove

window.addEventListener("touchstart", function() {});

window.addEventListener("touchend", function() {});

window.addEventListener("touchmove", function() {});

Web Storage

Web Storage

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:

  • sessionStorage: è una memorizzazione sempre di dati in formato stringa, ma che verranno eliminati alla chiusura del tab del browser
  • localStorage: come sessionStorage, ma le informazioni memorizzate persistono anche dopo la chiusura del tab del browser

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.

Scrittura su Web Storage

// 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);

Lettura su Web Storage

// 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'));

Cancellazione da Web Storage

// ELIMINO SOLO IL VALORE CON LA CHIAVE pigreco
localStorage.removeItem("pigreco");

// ELIMINO TUTTI I VALORI PRESENTI
sessionStorage.clear();

Esercizi

1) Realizzare una piccola applicazione per il meteo in tempo reale. L'applicazione deve anche permettere di inserire nuove città e di avere il meteo si ogni singola città

 

2) Usare le api Geolocation per recuperare la propria posizione e stamparla a video

Made with Slides.com