SSE推送失败主因在服务端:需200状态码、text/event-stream类型、no-cache缓存控制、换行结尾、保持连接;Node/PHP/Python/Nginx均有特定配置陷阱,调试应优先curl验证流式响应。

HTML 本身不“做” SSE 推送,EventSource 只负责接收,真正的推送必须由服务端发起 —— 如果你前端写了 new EventSource('/events') 却收不到数据,90% 的问题出在后端响应头或流式输出没写对。
为什么 EventSource 一直 pending 或报错 net::ERR_INCOMPLETE_CHUNKED_ENCODING
这是最常见阻塞点:浏览器等待合法的 SSE 响应流,但服务端没按规范返回。SSE 要求:
- 响应状态码必须是
200(不能是304、204等) - 必须设置
Content-Type: text/event-stream - 必须设置
Cache-Control: no-cache(部分浏览器如 Safari 对no-store更敏感,可加must-revalidate) - 响应体必须以换行符结尾(哪怕只发一个
data:,也要补\n\n) - 不能提前关闭连接,也不能用普通
res.end()结束响应(Node.js)或print()后退出(Python)
示例(Node.js/Express):
app.get('/events', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, must-revalidate',
'Connection': 'keep-alive'
});
// 发一条初始化消息(可选)
res.write('data: {"status":"connected"}\n\n');
const timer = setInterval(() => {
res.write(`data: {"time":${Date.now()}}\n\n`);
}, 1000);
req.on('close', () => {
clearInterval(timer);
res.end();
});
});
前端 EventSource 怎么处理重连、自定义事件、错误兜底
默认重连间隔是 3 秒,但不可靠;error 事件不区分网络断开、服务端崩溃还是 CORS 失败;自定义事件名(如 message、update)需要显式监听。
- 重连控制:在
onerror里手动new EventSource,并递增延迟(避免雪崩),不要依赖retry:字段(Chrome 不支持) - 自定义事件:服务端发
event: update\n data: ...\n\n,前端用source.addEventListener('update', ...) - 错误判断:检查
event.target.readyState === 0表示连接未建立,=== 0且反复触发error很可能是跨域或路径 404 - CORS:服务端必须带
Access-Control-Allow-Origin,且不能为*(若带 credentials)
简写前端逻辑:
let source = new EventSource('/events');
source.onopen = () => console.log('connected');
source.onerror = () => {
if (source.readyState === 0) {
console.log('reconnecting...');
setTimeout(() => (source = new EventSource('/events')), 5000);
}
};
source.addEventListener('update', e => console.log(JSON.parse(e.data)));
PHP / Python / Nginx 下的典型陷阱
动态语言和反向代理常默默破坏流式响应:
立即学习“前端免费学习笔记(深入)”;
- PHP:默认开启
output_buffering,必须ob_end_flush()+flush()+ob_flush()三连;禁用zlib.output_compression - Python(Flask):不能用
return,要用Response(..., content_type='text/event-stream')并确保生成器 yield 后不退出;Gunicorn 需设--timeout 0和--keep-alive 5 - Nginx:默认缓冲响应体,必须加
proxy_buffering off;、proxy_cache off;、proxy_http_version 1.1;和proxy_set_header Connection '';
尤其注意 Nginx 的 proxy_buffering off —— 缺了它,即使后端发了 10 条 data:,Nginx 也会攒够 4KB 才吐给浏览器,导致严重延迟。
SSE 的核心约束很硬:服务端必须维持长连接、逐块 flush、严格遵循响应头与格式;任何中间层(CDN、WAF、负载均衡)都可能截断或缓存流。调试时优先 curl 测试原始响应流是否实时分块输出,再查前端控制台 Network 标签页里 /events 的 Response 内容是否随时间滚动 —— 这比看 JS 控制台报错更直接。



















