Loading...

HTML Server-Sent Events (SSE)

Previously, Web Workers ran JavaScript in a background thread and talked to the page with postMessage — local CPU work, no server stream. This lesson leaves off-thread compute and introduces Server-Sent Events (SSE): the server pushes a stream of text updates to the browser over HTTP. Your HTML page still loads a script; that script opens EventSource, listens for message, and paints the DOM when e.data arrives. Scope stays practical — open, listen, one-way push — not Node stream servers, Django Channels products, or a full realtime architecture course.

Why SSE in an HTML course

Beginners need live scores, logs, or status lines without inventing a custom socket protocol. SSE is the common first browser API for “server pushes text over HTTP.” After Web Workers’ “page and worker message locally,” this lesson’s split is different: the server owns the stream; the page script owns EventSource and the DOM. You need new EventSource(url), onmessage / onerror, and the idea that the response is text/event-stream — enough for intro pages without building a chat backend or a WebSocket fleet.

Direct answer

1) Create const es = new EventSource("/events") (use a real stream URL when you have a backend).
2) Handle es.onmessage (or addEventListener("message", …)) and read e.data.
3) Update the DOM on the page when events arrive.
4) Handle es.onerror for disconnect / retry awareness.
5) SSE is one-way: server → browser. Browser→server needs a normal request or a different tool.
6) Prefer WebSockets when you need full duplex chat-style messaging; prefer polling when updates are rare; prefer Workers when the work is local CPU, not a server stream.

📊 SSE vs WebSocket vs Worker

Topic SSE (this lesson) WebSocket Web Worker (prev)
Typical role Server→browser text stream Full duplex messages Local off-thread compute
Browser entry EventSource(url) new WebSocket(url) new Worker(url or Blob)
Direction One-way (server push) Two-way Page ↔ worker (no server required)
Transport idea HTTP text/event-stream WS protocol postMessage / onmessage
DOM updates On the page script On the page script On the page script only
This course depth Required (browser pattern) Contrast only Previous lesson
Not this lesson Full backend stream servers Chat product design SharedWorker fleets

Tiny EventSource listen pattern

This snippet shows the browser side only. /events must be a real SSE endpoint on your host; without a server the connection errors — that still teaches the API shape.

EventSource listen pattern

html
<pre id="out">Waiting for stream…</pre>
<script>
const out = document.getElementById("out");
const es = new EventSource("/events");
es.onmessage = function (e) {
out.textContent = "Last update: " + e.data;
};
es.onerror = function () {
out.textContent = "SSE error or closed (need a real /events stream)";
};
</script>

Reading the listen calls

  • new EventSource("/events") opens a long-lived HTTP stream to that path
  • onmessage runs when the server sends a default message event
  • e.data holds the text payload for that event
  • The page writes into <pre> — same DOM ownership rule as Workers, different source of data
  • Unlike Web Workers, nothing uses postMessage to a background thread — this is server push
  • Without a compatible server, onerror is expected in local demos
  • Keep intros tiny: one URL, one handler, one DOM write

Append stream lines to a log

Live UIs often append each event instead of replacing one line. This demo keeps the last few lines in a list when messages arrive.

Append SSE lines to a log

html
<ul id="log"></ul>
<script>
const log = document.getElementById("log");
const es = new EventSource("/events");
es.onmessage = function (e) {
const li = document.createElement("li");
li.textContent = e.data;
log.appendChild(li);
while (log.children.length > 5) {
log.removeChild(log.firstChild);
}
};
es.onerror = function () {
if (!log.dataset.noted) {
log.dataset.noted = "1";
const li = document.createElement("li");
li.textContent = "Stream not available — wire a text/event-stream URL";
log.appendChild(li);
}
};
</script>

Reading the log idea

  • Each onmessage creates a new <li> from e.data
  • Cap the list so demos stay readable
  • Still one-way: the page does not postMessage back through EventSource
  • Still not a Web Worker — no Blob worker, no off-thread sum loop
  • Named events (addEventListener("ping", …)) exist in the API; default message is enough for intro
  • Call es.close() when you no longer need the stream
  • Next optional lesson: XHTML history and polyglot markup — a different HTML-course topic

Choosing SSE, polling, sockets, or workers

  • Server pushes frequent status/log lines over HTTP: good intro SSE fit
  • Rare refresh every few minutes: simple polling may be enough
  • Chat that must send both ways continuously: consider WebSockets
  • Heavy local loop that freezes scrolling: that was Web Workers, not SSE
  • Drag a card into a dashed zone: that was Drag and Drop
  • Building the Node/Django stream endpoint itself: beyond this HTML browser intro

Practice — open, listen, contrast

  1. Read the EventSource listen snippet; note onmessage and onerror.
  2. Skim what a text/event-stream response looks like in trusted docs (data: lines).
  3. Read the append-log snippet; explain why the page updates the DOM, not the server.
  4. Write one sentence: Web Workers compute locally off-thread; SSE receives server-pushed events.
  5. Write one sentence: SSE is one-way; WebSockets are the usual full-duplex alternative.
  6. (Optional) Point EventSource at a real tutorial SSE URL when you have a backend.
  7. Peek ahead: XHTML covers stricter XML-style markup history — not live streams.

Easy mistakes

  • Expecting EventSource to send browser→server payloads like a WebSocket
  • Confusing SSE with Web Workers (server stream ≠ background CPU thread)
  • Forgetting the server must speak a compatible event-stream format / content type
  • Using SSE for updates so rare that a single fetch would do
  • Ignoring onerror so silent failures look like a “broken” page
  • Treating this intro as a full backend streaming or WebSocket product course
  • Mixing up EventSource with Worker or WebSocket constructors

Summary

  • SSE streams server→browser text updates over HTTP
  • Use EventSource, handle onmessage / onerror, paint the DOM on the page
  • One-way push; WebSockets when you need full duplex
  • Web Workers were local off-thread compute; this lesson is server push
  • Real demos need a text/event-stream URL; the browser pattern still matters alone
  • Next: HTML XHTML for XML-style document history in the course

🧠 Test Your Knowledge

Ready to Start

Test Your Knowledge

Challenge yourself with this interactive quiz and see how well you understand the topic

❓
5
Questions
🎯
70%
To Pass
♾️
∞
Time
🔄
∞
Attempts

📝 Instructions

  • Read each question carefully
  • Select the best answer for each question
  • You can retake the quiz as many times as you want
  • Your progress will be shown at the top