Understanding Server‑Sent Events (SSE): Concepts, Comparison with Polling and WebSocket, and Practical Implementation
This article explains the scenarios where servers need to push data to clients, compares three implementation methods—polling, WebSocket, and SSE—highlights their advantages and drawbacks, and provides step‑by‑step frontend and Node.js backend demos for building a real‑time SSE connection.
Introduction
In many daily development scenarios, the server must actively push data to the client, such as real‑time dashboards, unread messages, or chat features. This article introduces the use cases of Server‑Sent Events (SSE) and demonstrates how to use SSE.
Server‑to‑Client Push Implementation Options
The three common solutions are:
Polling
WebSocket
SSE
Polling Overview
Polling simulates push by repeatedly sending HTTP requests from the client. It is considered the least efficient method because each request incurs the full HTTP handshake, consumes browser concurrency slots, and cannot guarantee timely data delivery.
Drawbacks of Polling:
Repeated HTTP handshake for every request, causing unnecessary overhead.
Client must keep sending requests for the entire page lifetime, which is unfriendly to resources.
Browser limits concurrent connections per domain (e.g., Chrome allows only 6), and long‑running polls occupy these slots.
Long polling intervals may lead to delayed data.
WebSocket Overview
WebSocket provides a full‑duplex communication channel, allowing both client and server to send messages independently. It is powerful but requires a separate ws/wss protocol, which older browsers may not support.
Browser Compatibility: Not all browsers support the WebSocket protocol.
SSE Overview
SSE is a one‑way communication protocol built on top of HTTP. It allows the server to push data to the client but does not support client‑to‑server messages.
Long connections (HTTP/1.1 persistent connections) enable multiple requests/responses over a single TCP connection, reducing server load and improving performance.
SSE is lightweight, uses standard HTTP, and works with any server that supports HTTP without extra configuration. Note: Internet Explorer does not support SSE.
Differences Between WebSocket and SSE
WebSocket is full‑duplex; SSE is one‑way (server‑to‑client).
WebSocket requires server support for the ws protocol; SSE works over existing HTTP servers.
SSE is simpler and lighter; WebSocket is more complex.
SSE automatically handles reconnection; WebSocket needs custom handling.
SSE allows custom data types.
Use Cases
Use SSE for scenarios that only need server‑to‑client push, such as real‑time dashboards or notification centers. Use WebSocket when bidirectional communication is required, like chat applications.
SSE Main API
Creating an SSE connection in JavaScript:
var source = new EventSource(url);
SSE Connection States
EventSource.CONNECTING (0) : Connection not yet established or disconnected.
EventSource.OPEN (1) : Connection established and ready to receive data.
EventSource.CLOSED (2) : Connection closed and will not reconnect.
SSE Events
open : Triggered when the connection is opened.
message : Triggered when data is received.
error : Triggered on communication errors.
Demo: Implementing an SSE Connection
Frontend (HTML + JavaScript)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="ul"></ul>
<script>
function createLi(data) {
let li = document.createElement("li");
li.innerHTML = String(data.message);
return li;
}
let source = '';
if (!!window.EventSource) {
source = new EventSource('http://localhost:8088/sse/');
} else {
throw new Error("当前浏览器不支持SSE");
}
source.onopen = function(event) {
console.log(source.readyState);
console.log("长连接打开");
};
source.onmessage = function(event) {
console.log(JSON.parse(event.data));
console.log("收到长连接信息");
let li = createLi(JSON.parse(event.data));
document.getElementById("ul").appendChild(li);
};
source.onerror = function(event) {
console.log(source.readyState);
console.log("长连接中断");
};
</script>
</body>
</html>Backend (Node.js + Express)
const express = require('express');
const app = express();
const port = 8088;
// CORS configuration
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
if (req.method == 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
app.get('/sse', (req, res) => {
res.set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
console.log('进入到长连接了');
setInterval(() => {
const data = { message: `Current time is ${new Date().toLocaleTimeString()}` };
res.write(`data: ${JSON.stringify(data)}\n\n`);
}, 1000);
});
app.listen(port, () => {
console.log(`项目启动成功 - http://localhost:${port}`);
});Conclusion
SSE is lighter than WebSocket and works over standard HTTP.
Use SSE when only server‑to‑client push is needed.
Use WebSocket for full bidirectional communication.
Polling should be avoided due to high resource consumption.
IE does not support SSE; mini‑programs also lack SSE support.
Top Architecture Tech Stack
Sharing Java and Python tech insights, with occasional practical development tool tips.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.