Cette traduction est incomplète. Aidez à traduire cet article depuis l'anglais.
Développer une application web qui utilise 'server-sent events' est assez facile. Vous aurez besoin d'un bout de code coté serveur qui va transmettre des informations en continu a l'application web, du côté de l'application web cela fonctionne à peu de chose près comme pour la plupart des événements.
Recevoir des événements du serveur
L'API SSE est contenue dans l'interface EventSource
qui permet d'ouvrir une connection vers le serveur et commencer a recevoir des événements du serveur, vous devez créer un nouvelle objet EventSource, en spécifiant une URL d'un script coté serveur qui va générer les événements.
Par exemple :
var evtSource = new EventSource("ssedemo.php");
Une fois que vous avez instancié votre source d'événement, vous pouvez commencer à écouter les messages du serveur.
evtSource.onmessage = function(e) { var newElement = document.createElement("li"); newElement.innerHTML = "message: " + e.data; eventList.appendChild(newElement); }
Ce code écoute les messages entrants (qui viennent du serveur) et ajoute les messages textes a la suite de la liste HTML.
Vous pouvez aussi utiliser un écouteur d'événement avec addEventListener()
:
evtSource.addEventListener("ping", function(e) { var newElement = document.createElement("li"); var obj = JSON.parse(e.data); newElement.innerHTML = "ping at " + obj.time; eventList.appendChild(newElement); }, false);
Ce code est similaire, à part qu'il sera appelé automatiquent avec le champ d'événement réglé sur "ping"; il transforme ensuite le message en format JSON du champ data et l'affiche.
Envoyer un événement depuis le serveur
Le script coté serveur qui envoie l'événement doit répondre en utilisant le type MIME text/event-stream. Chaque notification est envoyée en tant que bloc de texte qui finit par une paire de nouvelles lignes. Pour plus de détails sur le format d'envoi en continu, voir "Event Stream Format".
Voici le code PHP que nous utilisons pour notre exemple :
date_default_timezone_set("America/New_York"); header("Content-Type: text/event-stream\n\n"); $counter = rand(1, 10); while (1) { // Chaque seconde, envoi d'un evenement de type "ping". echo "event: ping\n"; $curDate = date(DATE_ISO8601); echo 'data: {"time": "' . $curDate . '"}'; // Paire de nouvelle ligne echo "\n\n"; // Envoie un message simple à des intervalles aléatoires. $counter--; if (!$counter) { echo 'data: This is a message at time ' . $curDate . "\n\n"; $counter = rand(1, 10); } ob_flush(); flush(); sleep(1); }
Ce code génère un événement "ping" chaque seconde. Chaque événement est un objet JSON, dans ce cas, juste ISO 8601 timestamp qui correspond à l'heure a laquelle l'événement a été généré. A intervalle aléatoire, un message simple (sans type d'événement) est envoyé.
Gestion d'erreurs (Error handling )
Losqu'un événement survient (tel un délai réseau trop long ou un problème d'autorisation d'accès), un événement erreur (error event) est généré. À partir de l'événement onerror de l'objet EventSource vous pouvez récupérer l'erreur et effectuer le traitement à l'aide d'une fonction javascript.
evtSource.onerror = function(e) { alert("EventSource failed."); };
Jusqu'à Firefox 22, il semble qu'il n'y ait aucune façon de distiguer les différentes événements erreur possible.
Fermeture de connexion (Closing event streams)
Par défaut, si la communication entre le client et le serveur est interrompue, la connexion sere réinitialisée. Également, il est possible de terminer la connexion à l'aide de la méthode .close() de l'objet EventSource.
evtSource.close();
Format du flux d'événements (Event stream format)
Le format du flux d'événements est une chaine de données texte simple codées en UTF-8. Chaque chaine de message doit être séparé par deux lignes d'espacement.
Note : Le caractère deux point (:) utilisé en début de chaine indique un message de commentaire. Ce type de message peut être utilisé pour maintenir l'état de la connexion active.
data: avec deux lignes
Chaque message est formé d'une ou plusieurs lignes de texte dans laquelle on retrouve certains champs. Le nom du champ doit apparaitre en début de message suivit du caractère deux points (:
). Ensuite, la valeur du champ doit suivre sous forme d'une chaine de texte.
Champs
Les champs suivants sont définis par la spécification :
event
- Le champ
event
corespond au type d'événement. Si le type d'événement est spécifié il sera envoyé vers le navigateur au gestionnaire définie pour l'événement spécifié. Le script doit contenir un gestionnaire avec le nom de l'événement a récupérer. data
- Le champ
data
correspond au message qui sera échangé. Lorsque l'objetEventSource
reçois plusieurs lignes de messages consécutives commençant par le champdata:
il en fera automatiquement la concaténation en ajoutant un code de retour (\n
) entre chaque chacune d'elle. Sur la dernière lignedata
le dernier code de retour (\n
) sera supprimé. id
- Le champ
id
correspond à un numéro ID que l'on peut attribuer à un événementEventSource
. Ce numéro peut être récupéré à l'aide de la propriétéevent.id
evtSource.onmessage = function(e) { if(e.id === 911) alert('Message 911'); }
retry
- Le délai de reconnexion est d'environ 3 secondes par défaut (3000). Le champ
retry
correspond au délai avant reconnexion. Le nombre suivant le champ retry doit être un entier qui représente le nombre de milième de seconde avant la reconnexion. Si une valeur invalide est spécifiée le champretry
sera ignoré et la valeur par défaut sera utilisée.
Tous les autres champs autres que ceux décrit précédemment seront ignoré.
Note:
Si une ligne de message ne contient aucun symbole deux points ( : )
, la ligne entière sera traité comme un nom de champ et le contenu sera considéré comme étant vide.
Exemples
Messages de données seulement
Dans l'exemple suivant, on retrouve trois message envoyés. Le premier correspond seulement a un commentaire puisqu'il débute par le caractère deux points (:)
Tel que mentionné précédemment, ce type de message peut être utilisé pour maintenir la connexion si des messages doivent être transmis de façon irrégulière.
Le second message contient un champ data
avec la valeur "some text"
. Le troisième message contient un champ data
répartie sur deux lignes. Ce message deviendra "another message\nwith two lines"
du côté client. Notez que le caractère de retour (\n)
sera inséré entre les deux lignes de message.
: this is a test stream data: some text data: another message data: with two lines
Événements nommés
Cet exemple transmets une série d'événements nommés. Chacun des messages a un nom spécifique qui est précédé par le champ event:
tandis que le champ data:
contient une chaine de données formatée JSON qui pourra être récupéré du côté client sur un événement message avec une instruction du genre var message = JSON.parse(e.data).
Le champ data
peut évidemment contenir une chaine de texte simple sans nécessairement être formaté JSON.
event: userconnect data: {"username": "bobby", "time": "02:33:48"} event: usermessage data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."} event: userdisconnect data: {"username": "bobby", "time": "02:34:23"} event: usermessage data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}
Messages mélangés
Vous n'êtes pas obligé d'utiliser seulement des messages avec des événements nommés ou des chaines de données formatées JSON. Vous pouvez mélanger les deux types de messages dans un même événement. Dans cet exemple, l'événement 'userconnect'
contient à la fois une chaine JSON suivi d'une chaine de texte simple qui pourrait être utilisé pour préciser l'événement par exemple. Ensuite vient un deuxième événement 'usermessage'
qui contient une chaine JSON avec entre autre un message intégré dans l'un des champs du tableau associatif "text" : "Hi everyone."
event: userconnect data: {"username": "bobby", "time": "02:33:48"} data: Here's a system message of some kind that will get used data: to accomplish some task. event: usermessage data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}
Compatibilité des navigateurs
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
EventSource support | 9 | 6.0 (6.0) | Pas de support | 11 | 5 |
Feature | Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
EventSource support | Pas de support | ? | ? | 11.1 | 4 |
Références
WHATWG community
https://html.spec.whatwg.org/multipage/comms.html#server-sent-events
Eric Bidelman on HTML5 ROCKS blog
https://www.html5rocks.com/en/tutorials/eventsource/basics/?redirect_from_locale=fr