如何通过SSE捕获网络断开并阻止浏览器显示错误页面?
我正在使用Server-Sent-Events(SSE),发现网络连接断开时浏览器总会跳转到错误页面,先是显示“This site can't be reached”,随后显示“No Internet - ERR_INTERNET_DISCONNECTED”。我确定问题出在SSE连接上,因为服务器上其他未使用SSE的站点在网络断开后仍能正常显示。
我尝试用JavaScript捕获断开事件:
sse_source.onerror = function(e) { e.preventDefault(); // prevent default, not working if (sse_source.readyState == EventSource.CLOSED) { // close SSE source sse_source.close(); } // alert shows up and interrupts, but after clicking OK // the browser error page is displayed alert('Connection to Server lost. No Live Updates.'); }
但这毫无作用。我还尝试了:
window.addEventListener('offline', updateOnlineStatus); function updateOnlineStatus(e) { e.preventDefault(); // prevent default, not working sse_source.close(); alert('Connection to Server lost. No Live Updates.'); }
这里alert并未弹出,浏览器始终会显示错误页面。是否有其他JavaScript方法能让网站保持显示?
更新:
我在控制台中看到,连接断开时sse_source.onerror会完整执行,但无法阻止错误页面弹出。sse_source.onerror执行后,window.addEventListener('offline', updateOnlineStatus)也会执行,但同样无法阻止错误页面。另外,当我移除sse_source.readyState == EventSource.CLOSED判断后,sse_source.onerror中的alert能正常弹出,当时readyState的值为0。
核心原因
浏览器跳转错误页是因为SSE连接持续失败未被正确处理,被判定为页面级加载失败。以下是具体解决步骤:
1. 重构SSE连接的错误处理与重连逻辑
放弃无效的e.preventDefault(),主动关闭失效连接并发起重连,避免浏览器持续重试触发错误页:
let sseSource; const reconnectDelay = 3000; // 3秒后重连 function initSSE() { sseSource = new EventSource('/your-sse-endpoint'); sseSource.onmessage = (e) => { // 处理收到的SSE消息 console.log('Received:', e.data); }; sseSource.onerror = () => { // 立即关闭当前失效连接 sseSource.close(); // 显示页面内提示(替代alert) const alertEl = document.getElementById('connection-alert'); alertEl.style.display = 'block'; alertEl.textContent = '连接已断开,正在尝试重连...'; // 定时发起重连 setTimeout(initSSE, reconnectDelay); }; sseSource.onopen = () => { // 重连成功后隐藏提示 document.getElementById('connection-alert').style.display = 'none'; }; } // 页面加载完成后初始化SSE window.addEventListener('load', initSSE);
2. 用页面内提示替代alert
alert会阻塞线程,导致浏览器在弹窗关闭后继续处理错误逻辑。提前在页面中添加提示元素:
<div id="connection-alert" style="position: fixed; top: 0; left: 0; width: 100%; background: #ff4444; color: #fff; padding: 12px; text-align: center; display: none; z-index: 9999;"></div>
3. 结合网络状态事件优化连接管理
配合online/offline事件,在网络状态切换时主动管理SSE连接:
window.addEventListener('offline', () => { if (sseSource && sseSource.readyState !== EventSource.CLOSED) { sseSource.close(); document.getElementById('connection-alert').textContent = '网络已断开,请检查网络连接'; } }); window.addEventListener('online', () => { if (!sseSource || sseSource.readyState === EventSource.CLOSED) { initSSE(); document.getElementById('connection-alert').textContent = '网络已恢复,正在重新连接'; } });
关键注意事项
- 不要用
e.preventDefault()处理SSE错误:该事件没有可阻止的默认浏览器行为,调用无效。 - 放弃
EventSource.CLOSED判断:网络断开时readyState通常为0(CONNECTING),原判断会跳过关闭连接的逻辑,导致浏览器持续重试。 - 确保服务器返回正确响应头:必须包含
Content-Type: text/event-stream和Cache-Control: no-cache,避免缓存引发的错误判定。
内容的提问来源于stack exchange,提问作者Avatar

