Javascript EventSource持续重连PHP SSE端点问题咨询
SSE(Server-Sent Events)无限重连问题解析
问题描述
尝试用PHP和SSE实现简单Demo时,发现页面会无限次重连后端端点,而非仅调用一次。
PHP代码(sse.make-segment-snapshots.php)
ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); for ($i = 0; $i <= 5; $i++) { $time = date('r'); echo "data: The server time is: {$time}\n\n"; flush(); } echo "data: END-OF-STREAM" . "\n\n"; flush();
JS/jQuery代码
$('.btn-snap-all').on('click', function () { const source = new EventSource('sse.make-segment-snapshots.php'); const listener = function (event) { if(typeof event.data !== 'undefined'){ console.log(event.data); } }; source.addEventListener('open', listener, false); source.addEventListener('message', listener, false); source.addEventListener('error', listener, false); return false; });
原因分析
这是预期行为,但和你对SSE的设计逻辑理解有偏差:
- EventSource的核心机制是:一旦后端连接关闭,它会自动尝试重新建立连接(默认重连间隔为3秒)。
- 你的PHP脚本执行完循环和最后一条消息后,会自动终止进程、关闭HTTP连接,前端的EventSource检测到连接断开后,就会触发内置的重连机制,导致无限循环请求。
解决方法
根据你的业务需求,有两种常见处理方式:
1. 后端保持长连接(持续推送场景)
如果需要持续推送数据,PHP脚本要保持运行不终止,可通过循环+sleep实现,注意提前禁用脚本超时:
ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); // 禁用脚本执行超时限制 set_time_limit(0); header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); $i = 0; while ($i <= 5) { $time = date('r'); echo "data: The server time is: {$time}\n\n"; flush(); // 每秒推送一次数据 sleep(1); $i++; } echo "data: END-OF-STREAM\n\n"; flush();
2. 客户端收到结束信号后主动关闭连接(一次性推送场景)
如果只是一次性推送完数据就结束,在前端收到END-OF-STREAM消息时,调用source.close()关闭EventSource,阻止自动重连:
$('.btn-snap-all').on('click', function () { const source = new EventSource('sse.make-segment-snapshots.php'); const listener = function (event) { if(typeof event.data !== 'undefined'){ console.log(event.data); // 检测到结束信号,主动关闭连接 if (event.data === 'END-OF-STREAM') { source.close(); } } }; source.addEventListener('open', listener, false); source.addEventListener('message', listener, false); source.addEventListener('error', listener, false); return false; });
额外提示
- 后端推送消息时,必须确保每个
data:字段后都带有两个换行符(\n\n),这是SSE的强制格式要求,否则前端可能无法正确解析消息。 - 若后端因超时、错误等异常情况关闭连接,EventSource同样会触发重连,可在
error事件中添加异常处理逻辑。
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

