HTML5 Server-Sent Events

9 aprile 2013

Grafici dinamici con i Server-Sent Events

Vediamo come costruire qualcosa di più complesso: supponiamo di dover sviluppare un grafico legato ad alcuni indici che variano molto velocemente e di volere che questa variazione si rifletta il prima possibile all’interno dell’interfaccia utente. Possiamo creare una sorgente remota che risponda ad ogni interrogazione con il valore attuale degli indici ed utilizzare un EventSource lato client per recuperare queste informazioni.

Per prima cosa costruiamo la sorgente remota, per le finalità dell’esempio andrà benissimo generare il valore degli indici in modo random, ovviamente in un ambiente di produzione dovremmo interrogare il database. Creiamo un nuovo file ‘tick.php‘ all’interno della cartella di progetto:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
echo 'data: {"data1": '. rand(1,10) . ',"data2": '. rand(1,10) . ',"data3": '.
rand(1,10) . ',"data4": '. rand(1,10) . '}' . PHP_EOL;
echo PHP_EOL;
?>

Possiamo notare come il messaggio di testo sia stato serializzato in JSON, questo rende facile inviare attraverso queste API anche strutture più complesse del semplice messaggio testuale. Ora passiamo al client: creiamo una pagina: ‘grafico.html‘ così strutturata:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Un semplice grafico</title>
<style>
section
{
    position:relative;
    height: 100px;
    width: 100%;
    background: gray;
}

div
{
    position: absolute;
    background: red;
    width: 50px;
    bottom: 0px;
    -webkit-transition: height 1s;
    -moz-transition: height 1s;
    transition: height 1s;
}
div:nth-child(1){ left: 10px; }
div:nth-child(2){ left: 70px; }
div:nth-child(3){ left: 130px; }
div:nth-child(4){ left: 190px; }
</style>
</head>
<body>
<section>
<div></div>
<div></div>
<div></div>
<div></div>
</section>

<script>
var stocks = new EventSource("tick.php");

stocks.addEventListener('message', function (event) {

    var graph_data = JSON.parse(event.data),
        d1 = document.querySelector('div:nth-child(1)'),
        d2 = document.querySelector('div:nth-child(2)'),
        d3 = document.querySelector('div:nth-child(3)'),
        d4 = document.querySelector('div:nth-child(4)');
    
	d1.style.height = "" + (graph_data.data1 * 10) + "px";
    d2.style.height = "" + (graph_data.data2 * 10) + "px";
    d3.style.height = "" + (graph_data.data3 * 10) + "px";
    d4.style.height = "" + (graph_data.data4 * 10) + "px";
});
</script>
</body>
</html>

In questo caso ad ogni evento ‘message‘ dobbiamo deserializzare il messaggio ricevuto e associare ad ogni barra del nostro grafico l’altezza corrispettiva all’indice che rappresenta.

Se proviamo ad eseguire il tutto in un browser con il supporto per queste API potremmo sperimentare una semplice ma efficace versione di un grafico animato che si aggiorna automaticamente alla variazione del dato sul server:

Esempio

Polyfill

Ecco due possibili polyfill per i browser che non supportano nativamente l’API, consigliati da Remy Sharp in un suo post interessantissimo su EventSource:

Se vuoi aggiornamenti su HTML5 Server-Sent Events inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su HTML5 Server-Sent Events

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy