Jakiś czas temu pisałem o wchodzącej do przeglądarek technologii, jaką jest Web Workers. Nadszedł więc czas na opisanie kolejnej, trochę podobnej technologii – Server-Sent Events.
Czym jest Server-Sent Events? Jest to API do wykonywania połączeń HTTP – wysyłania zdarzeń przez serwer do przeglądarki (komunikacja jednokierunkowa). Czyli mówiąc inaczej, jest to znajoma wszystkim komunikacja serwer-klient wywoływana bezpośrednio z JavaScript.
Mamy technologię XHR (AJAX), która również służy do komunikacji klient-serwer. Czym więc się różni AJAX od Server-Sent Events? Otóż w przypadku tej drugiej technologii serwer na bieżąco komunikuje się z klientem, wysyłając powiadomienia. Poza tym dochodzi kilka innych różnic i zmian, o czym za chwilę.
Obiekt EventSource i jego wykorzystanie
Wraz z Server-Sent Events pojawia się w nowszych przeglądarkach wbudowany obiekt – EventSource. Użycie jest bardzo podobne jak w przypadku Web Workers – zmienia się głównie nazwa obiektu oraz funkcjonalność :-)
Prosty przykład:
1 2 3 4 5 6 7 8 9 | document.addEventListener('DOMContentLoaded', function () { var source = new EventSource('http://localhost/blog/events.php'); source.addEventListener('message', function (event) { alert(event.data); }); }, false); |
Najpierw czekamy aż strona się wczyta do okna przeglądarki (DOMContentLoaded). Następnie tworzymy obiekt EventSource podając ścieżkę do pliku na serwerze, po czym dodajemy obsługę dla zdarzenia message. Skrypt jest wykonywany na serwerze i zaczyna wysyłać odpowiedzi, do której dostajemy się przez event.data. Proste i przyjemne w obsłudze :-)
Natomiast nasz plik events.php może wyglądać następująco:
1 2 3 4 5 6 7 8 9 10 11 | <?php header("Cache-Control: no-cache"); header("Content-Type: text/event-stream\n\n"); ?> data: foo data: bar data: foo data: bar |
Jak widzisz, wygląda dość nietypowo. Po pierwsze i najważniejsze, musimy ustawić nagłówek Content-Type na text/event-stream. Jest to nowy typ wymyślony na potrzeby tej technologii i zwracana odpowiedź jest w specjalny sposób traktowana: najpierw definiujemy element data, podstawiamy jakąś wartość i klikamy dwa razy enter. W ten sposób rozdzielamy wiadomości i możemy utworzyć ich nawet kilka w jednym pliku.
Poza tym dobrze by było też ustawić nagłówek Cache-Control na no-cache.
Tworząc plik w powyższy sposób w oknie przeglądarki po chwili wyskoczy nam alert o treści „foo”, kolejny alert: „bar” i trzeci „foo bar”.
Pozostałe możliwości Server-Sent Events
Dla obiektu EventSource możemy wywołać jeszcze inne metody:
- open – zdarzenie to informuje o nawiązaniu połączenia z plikiem na serwerze,
- error – dodając obsługę tego zdarzenia możemy w przyjazny sposób obsłużyć wszelkie błędy spowodowane nienawiązaniem połączenia z serwerem,
- close – pozwala zamknąć połączenie z serwerem, tak by przestał wysyłać zdarzenia:
1source.close();
Wsparcie dla jQuery
Dla obiektu EventSource został już napisany plugin do jQuery, który jeszcze bardziej ułatwia pracę z tym mechanizmem.
Zastosowanie powyższego pluginu jest o tyle dobre, że zapewniono w nim wsparcie dla przeglądarek nie obsługujących obiektu EventSource (poprzez zastosowanie obiektu XMLHttpRequest). W związku z tym polecam jego wykorzystanie, jeśli już chcemy korzystać z Server-Sent Events :-)
W jakich przeglądarkach ten obiekt jest dostępny? Czy w ogóle używanie tego na produkcji ma jakiś sens w chwili obecnej, czy lepiej trochę poczekać?
Tylko Chrome i Safari obecnie obsługują, z tego co widzę :-) Używać na produkcji jak najbardziej można, ale tylko i wyłącznie przy pomocy wyżej wspomnianego pluginu do jQuery. Dzięki temu nawet jeśli przeglądarka nie obsługuje EventSource to mamy natywne wsparcie przy pomocy XHR zapewnione przez plugin.
Brzmi ciekawe, czyżby koniec z wysyłaniem XHR co sekundę? Może w końcu pojawią się prawdziwie interaktywne aplikacje webowe. ;]
na pewno wszystko to zmierza w dobrym kierunku i przyśpieszy tworzenie aplikacji / tworzone aplikacje :-)
Bardzo przydatna techonologia, ale nasuwa mi się pytanie, czy utrzymywanie ciągłego połączenia z klientem(jakie z pewnością będzie konieczne) nie stanowi z kolei innego problemu. O ile się nie mylę najpopularniejszy serwer, czyli Apache(jeszcze?) dla każdego połączenia wydziela oddzielny wątek co przy bardzo dużej ilości połączeń bedzie dla serwera nie lada wyzwaniem. Mimo to przy wysokiej częstotliwości zapytań ta metoda może wpłynąć korzystnie na działanie naszej maszyny, tym bardziej jeśli zwykle na zapytanie wysyłana jest pusta odpowiedź. Myślę, że temat warto dogłębniej przeanalizować, a wnioski z dyskusji byłyby bardzo wartościowe.
@kewals:
Niby racja, choć wydaje mi się, że serwer nie będzie tworzyć kolejnych wątków, o ile w nagłówkach będziemy zostawiać otwarte połączenie. Mowa tutaj o nagłówku Connection:
Nie testowałem, ale pewnie tak to wygląda w praktyce.