Server Sent Events(SSE) - co to jest?

fsgeek.pl 4 lat temu

Server Sent Events (SSE) jest mechanizmem, który pozwala na jednokierunkową komunikację pomiędzy serwerem a klientem. Możemy przy jego pomocy wysyłać wiadomości i informować klienta o zmianach na serwerze. Brzmi znajomo? Najczęściej taka funkcjonalność kojarzy nam się z Websocket? Jaka jest pomiędzy nimi różnica, kiedy powinniśmy korzystać z SEE i jak z tego skorzystać?

Websocket vs SSE

Idea Server Sent Events jest podobna do Websocketów. To co różni oba rozwiązania to sposób komunikacji pomiędzy serwerem a klientem (czyli aplikacją w przeglądarce). W Websocketach mamy do czynienia z komunikacją dwukierunkową - oprócz tego, iż serwer wysyła dane do klienta to klient może również wysłać odpowiedź na serwer. SSE działa trochę inaczej - wiadomości może jedynie wysyłać serwer do klienta. Jest to pewne ograniczenie ale w większości przypadków jest to wystarczająca funkcjonalność.

Kiedy wykorzystywać SSE?

Tak jak wspomniałem w poprzednim akapicie wszystko zależy od tego co tworzymy. jeżeli są to różnego rodzaju chaty gdzie potrzebujemy komunikacji dwukierunkowej to oczywistym wyborem będzie Websocket. Jednak jeżeli potrzebujemy żeby informować stronę o pojedynczych zdarzeniach np.:

  • Koniec importu dużego pliku,
  • Koniec przetwarzania danego elementu,
  • Zmiana na backendzie np.: zmiana danych i konieczność odświeżenia widoku,

wtedy wykorzystanie SSE będzie lepszym rozwiązaniem.

Jak zaimplementować SSE?

Z racji tego, iż będziemy tutaj otrzymywać wiadomości z serwera implementację musimy podzielić na dwie części: klienta i serwera. Zaczniemy od części serwerowej. Aby móc wysyłać takie zdarzenia musimy ustawić odpowiednie nagłówki w odpowiedzi na zapytanie:

  • 'Content-Type': 'text/event-stream',
  • 'Cache-Control': 'no-cache',
  • 'Connection': 'keep-alive',

Mając tak ustawione nagłówki jesteśmy w stanie wysłać wiadomości. Wiadomości mają oczywiście swoją strukturę, której trzeba przestrzegać. Mamy tam dostępne 4 pola:

  • data - tutaj musimy wpisywać dane jakie chcemy przekazać do klienta w postaci striga. jeżeli potrzebujemy przekazać jakis obiekt najprościej będzie wykorzystać JSON.stringify()
  • id - id zdarzenia
  • event - jeżeli wysyłamy kilka różnych zdarzeń możemy im nadać konkretne nazwy tak aby klient się subskrybował tylko na konkretne wiadomości
  • retry - liczba określająca czas ponownego połączenia podczas próby wysłania zdarzenia

Wiadomości przesyłamy jako zwykłe zmienne tekstowe np.: "data: 'message'". Pojedyncze wiadomości są rozdzielane podwójnym znakiem nowej linii \n\n. Przykład takiego endpointu w Express.js

const express = require('express'); const app = express(); app.get('/events', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*' }); res.flushHeaders(); let i = 0; setInterval(()=>{ res.write(`id: ${i}\n`); res.write(`event: event1\n`); res.write(`data: Message -- ${Date.now()}`); res.write(`\n\n`); i++ }, 5000) }); app.listen(3000);

To teraz przyszedł czas na obsługę tego po stronie klienta. Ogranicza się to tutaj tylko do wykorzystania API EventSource w przeglądarce. Podajemy tam podczas tworzenia nowej instancji obiektu adres pod którym oczekujemy otrzymywać zdarzenia

const event = new EventSource('http://localhost:3000/events')

Dalsza obsługa zależy od tego jakie zdarzenia będziemy wysyłać. Tak jak wspomniałem jednym z parametrów zdarzenia może być pole event. jeżeli go podamy to musimy skorzystać z metody addEventListener

event.addEventListener('event_name', (event)=>{ // obsługa })

Wszystkie inne zdarzenia są obsługiwane przy pomocy funkcji onmessage

event.onmessage = (event) => { //obsługa }

I adekwatnie tyle. Jak widzicie jest to proste - nie potrzebujemy żadnych dodatkowych bibliotek by otrzymywać aktualizację na żywo z serwera. Jestem ciekaw czy znaliście wcześniej to rozwiązanie? No i czy z niego korzystaliście?

Idź do oryginalnego materiału