Understanding Server‑Sent Events (SSE): Concepts, Comparison with Polling and WebSocket, and Implementation Demo
This article explains the principles and use cases of Server‑Sent Events (SSE), compares it with traditional polling and WebSocket solutions, outlines their advantages and drawbacks, and provides complete front‑end and Node.js/Express demo code to build a real‑time push system.
In everyday development we often encounter scenarios where the server needs to push data to the client, such as real‑time dashboards, unread‑message notifications, and chat features.
The article introduces Server‑Sent Events (SSE), describes three common push implementations—polling, WebSocket, and SSE—and discusses their strengths and weaknesses.
Polling Overview
Polling is a pseudo‑push technique where the client repeatedly sends HTTP requests to the server, creating unnecessary network overhead, consuming browser concurrency slots, and providing delayed data delivery.
Each request incurs a full HTTP handshake (three‑way handshake and four‑way termination).
The browser limits concurrent connections per domain (e.g., Chrome allows only six), causing long‑running polls to block other requests.
Long‑lasting polls are inefficient for timely data retrieval.
WebSocket Overview
WebSocket is a full‑duplex protocol that enables bidirectional communication between client and server, offering powerful features but requiring support for the ws/wss protocol, which older browsers may lack.
Compatibility varies across browsers, as shown in the accompanying image.
SSE Overview
SSE is a unidirectional, lightweight protocol built on top of HTTP/HTTPS that allows the server to push data to the client without requiring a separate protocol.
Long connections are an HTTP/1.1 persistent connection technique that reduces server load and improves performance.
Note: Internet Explorer does not support SSE.
Differences Between WebSocket and SSE
WebSocket provides full‑duplex communication; SSE is server‑to‑client only.
WebSocket needs server‑side support for the ws protocol; SSE works with any standard HTTP server.
SSE is simpler and lighter; WebSocket is more complex.
SSE automatically handles reconnection; WebSocket requires custom handling.
SSE allows custom data types.
Typical Use Cases
SSE is ideal for scenarios that only require server‑to‑client push, such as real‑time dashboards and message center notifications.
WebSocket is better suited for bidirectional communication like chat applications.
SSE Core API
Creating an SSE connection in JavaScript:
var source = new EventSource(url);Connection state constants:
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.
Key SSE events:
open – triggered when the connection is opened.
message – triggered when data is received.
error – triggered on communication errors.
Demo Implementation
Front‑end (index.html)
<!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>
// generate li element
function createLi(data) {
let li = document.createElement("li");
li.innerHTML = String(data.message);
return li;
}
// check SSE support
let source = '';
if (!!window.EventSource) {
source = new EventSource('http://localhost:8088/sse');
} else {
throw new Error("当前浏览器不支持SSE");
}
// connection opened
source.onopen = function(event) {
console.log(source.readyState);
console.log("长连接打开");
};
// receive message
source.onmessage = function(event) {
console.log(JSON.parse(event.data));
console.log("收到长连接信息");
let li = createLi(JSON.parse(event.data));
document.getElementById("ul").appendChild(li);
};
// connection error / closed
source.onerror = function(event) {
console.log(source.readyState);
console.log("长连接中断");
};
</script>
</body>
</html>Back‑end (Node.js with Express)
const express = require('express');
const app = express();
const port = 8088;
// CORS configuration
app.all('*', (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}`);
});Running the two files launches a simple SSE demo that pushes the current time to the browser every second.
Conclusion
SSE is lighter than WebSocket and works over standard HTTP, making it easy to deploy.
Use SSE when only server‑to‑client push is needed; choose WebSocket for full bidirectional communication.
Polling should be avoided due to high resource consumption.
IE does not support SSE, and 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.