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
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
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
Wszystkie inne zdarzenia są obsługiwane przy pomocy funkcji onmessage
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?