Server Sent Events(SSE) - co to jest?

Czas czytania: 2 min
Liczba słów: 434
Data: 17-03-2020
Udostępnij:
Cześć. Cieszę się, że czytasz mój post. Jeśli podoba ci się to co piszę i chcesz otrzymywać informacje o nowych postach to dołącz do mojego newslettera .

Jeśli zauważysz, że jakieś treści się zdezaktualizowały, a jesteś nimi zainteresowany to napisz do mnie na [email protected]. Zależy mi na tym aby tworzyć dla ciebie treści o największej jakości.
Dziękuję za pomoc i dołączenie do newslettera - to daje siły do pisania kolejnych postów.

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, że 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śli są to różnego rodzaju chaty gdzie potrzebujemy komunikacji dwukierunkowej to oczywistym wyborem będzie Websocket. Jednak jeśli 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, że 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śli potrzebujemy przekazać jakis obiekt najprościej będzie wykorzystać JSON.stringify()
  • id - id zdarzenia
  • event - jeśli 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śli 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 właściwie 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?

Jeśli podobał ci się ten artykuł to dołącz do newslettera. Dostaniesz dodatkowe treści do każdego postu oraz eksluzywne materiały, które pomogą ci pisac lepszy kod Chcę uzyskać dostęp do bonusów