Un graphique mis à jour avec les server-sent events
Aujourd’hui, on va parler des Server-sent events, une technologie permettant de recevoir des messages de la part du serveur.
Le code utilisé est disponible ici :
github generous-folks/demo-dashboard-server-sent-events no-readme
Nous allons découvrir ce que sont les SSE en construisant un graphique mis à jour toutes les secondes.
Fonctionnement
Les SSE fonctionnent de la manière suivante :
- Le client demande au serveur d’écouter une route
- Le serveur répond qu’il est d’accord pour que le client écoute
- Lorsque le serveur le souhaite il envoie des informations au client. Ce dernier reçoit un message qu’il peut traiter comme il le souhaite.
- Lorsque l’on ne veut plus recevoir de données le client ou le serveur peuvent interrompre la connexion
Support navigateur
Est-il vraiment nécessaire que je parle du navigateur dont on ne doit pas prononcer le nom ?
Quoi qu’il en soit, on peut utiliser un polyfill en cas de besoin.
Code
// server.js
const http = require("http");
const PORT = 5000;
http
.createServer((req, res) => {
/* Il est nécessaire d'indiquer au navigateur qu'il va
recevoir des données de type "text/event-stream" */
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Access-Control-Allow-Origin": "*",
});
setInterval(() => {
const data = {
value: Math.round(Math.random() * 100),
};
/* Les données envoyées doivent suivre un format précis.
Une chaine de caractères étant "data: mydata", suivi d'un "\n\n".
Si vous voulez transmettre du JSON il faudra le transformer en
chaine de caractère comme ci-dessous. */
res.write(`data: ${JSON.stringify(data)}`);
res.write("\n\n");
}, 1000);
})
.listen(PORT, () => console.log(`http://localhost:${PORT}`));
// client.js
import c3 from "c3";
/* L'objet EventSource nous permet d'écouter les événements
envoyés depuis le serveur. On l'instancie en lui passant l'URL
d'où proviendront les événements */
const evtSource = new EventSource("http://localhost:5000");
// Initialisation du graphique
const data = [30, 20, 10, 40, 15, 25];
const chart = c3.generate({
bindto: "#chart",
data: {
type: "area",
columns: [["Random", ...data]],
},
bar: {},
axis: {
y: {
max: 200,
min: 0,
},
},
});
/* On effectue un traitement uniquementlorsque
le serveur décide d'envoyer un message */
evtSource.onmessage = function (e) {
/* Le code ci-dessous est lié à C3.js, mais concrètement,
on souhaite afficher maximum 10 valeurs sur ce graphique */
if (data.length === 10) data.shift();
data.push(JSON.parse(e.data).value);
chart.load({
columns: [["Random", ...data]],
});
};
/* En plus des messages, il est possible d'écouter lorsque
la communication commence et lorsqu'il y a une erreur */
evtSource.onopen = function () {
console.log("Ah bogaaaas");
};
evtSource.onerror = function () {
// Je suis certain que vous aussi vous débugguez comme ça
console.error("Et merde !");
};
Websocket en moins bien ?
C’est pas moins bien, c’est différent !
Avantage des SSE sur les Websockets:
- Transport via HTTP plutôt que part un protocole spécifique
- Compatibilité avec les vieux navigateurs grâce aux polyfill
- Reprise de connexion native
- Pas de problèmes avec les pare-feux d’entreprises
Avantages des Websockets sur les SSE:
- Communication bi-directionnelle
- Supporte le transfert de données binaires
- ”Pas de limites” de connexions
Sur ce dernier point, il faut savoir que l’on peut avoir maximum 6 connexions ouvertes par navigateur concernant les SSE.
Conclusion
Les SSE font parti de ces technologies dont on entend peu parler. Pourtant, ils sont peu coûteux à mettre en place, 1 header, 1 format de données et le tour est joué.
En terme de cas d’utilisation, les notifications, un flux d’information ou encore la gestion de stock sont parfaitement envisageables.
Les usages possibles sont multiples, mais il faut garder à l’esprit les limitations d’une telle technologie. 6 connexions par navigateur et pas de transfert de données binaires.
Websocket ou SSE, maintenant vous avez le choix pour votre communication serveur → client
Merci de m’avoir lu.