背景
SSE(Server-Sent Events)是一种基于 HTTP 的单向通信协议,它允许服务端向客户端推送数据,从而实现实时更新。SSE 具有如下特点:
- 简单易用,不需要建立 WebSocket 连接
- 节流,节省网络流量,减少服务端压力
- 支持自动重连,可以提高消息的可靠性
在实际项目中,我们经常会用到 SSE 来实现实时消息推送,但是在客户端和服务端之间的网络状况并不总是稳定的,有可能因为网络波动等原因导致 SSE 连接断开。为了保证消息的可靠性,我们需要实现 SSE 断线重连机制。
本文将介绍 SSE 断线重连的实现方法,并提供相关示例代码。
实现方法
重连机制的原理
SSE 断线重连机制的原理是客户端定时检测 SSE 连接的状态,如果发现连接已经断开了,则重新建立 SSE 连接。
定时检测 SSE 连接状态
我们可以通过 EventSource 对象的 readyState 属性来检测 SSE 连接的状态,它有以下四种取值:
0表示连接正在建立,也就是调用EventSource构造函数之后但是还没有建立连接。1表示连接已经建立,但是还没有收到数据。2表示连接已经建立,并且正在接收数据。3表示连接已经关闭,无法再接收数据。
我们可以通过如下方式定时检测 SSE 连接状态:
// www.javascriptcn.com code example
function checkSSEStatus(sse) {
setInterval(() => {
if (sse.readyState === EventSource.CLOSED) {
// 重新建立 SSE 连接
sse = newEventSource();
}
}, 3000);
}
checkSSEStatus(sse);这段代码每隔 3 秒钟检查一下 SSE 连接的状态,如果发现连接已经关闭了,就重新建立 SSE 连接。
其中 sse 是一个 EventSource 对象的实例,需要在调用 checkSSEStatus 函数之前创建它。
断线重连时需要重新设置事件监听器
如果 SSE 连接断线重连,事件监听器也需要重新设置,否则我们无法接收到新的消息。
// www.javascriptcn.com code example
function newEventSource() {
const sse = new EventSource('/path/to/sse');
sse.onmessage = (event) => {
console.log(event.data);
// 处理服务器推送过来的数据
}
sse.onopen = (event) => {
console.log('SSE 连接已经建立');
}
sse.onerror = (event) => {
console.log('SSE 连接出错,正在尝试重新连接...');
// 出错的情况下也需要重新设置事件监听器
sse.close();
sse = newEventSource();
}
return sse;
}在重新建立 SSE 连接时,我们需要先关闭之前的连接,然后重新设置事件监听器。
在出错时增加重连延迟
如果网络不稳定,可能会出现短时间内多次连接失败的情况。为了避免频繁重连,我们可以在出错时增加重连延迟。
// www.javascriptcn.com code example
function newEventSource() {
const sse = new EventSource('/path/to/sse');
let reconnectDelay = 1000;
sse.onmessage = (event) => {
console.log(event.data);
// 处理服务器推送过来的数据
}
sse.onopen = (event) => {
console.log('SSE 连接已经建立');
// 连接成功后,将重连延迟重置为 1000 毫秒
reconnectDelay = 1000;
}
sse.onerror = (event) => {
console.log('SSE 连接出错,' + reconnectDelay / 1000 + '秒后将尝试重新连接...');
// 出错的情况下也需要重新设置事件监听器
sse.close();
setTimeout(() => {
sse = newEventSource();
// 延迟时间逐渐增加,最大值为 30 秒钟
reconnectDelay = reconnectDelay >= 30000 ? 30000 : reconnectDelay * 2;
}, reconnectDelay);
}
return sse;
}这段代码在出错时增加了重连延迟,每次连接失败之后,重连延迟时间逐渐增加。最大值为 30 秒钟,这样可以避免频繁重连对服务端造成不必要的压力。
示例代码
以下示例代码完整实现了 SSE 断线重连机制、延迟重连和事件监听器的重新设置。
// www.javascriptcn.com code example
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>SSE 断线重连示例</title>
</head>
<body>
<h1>SSE 断线重连示例</h1>
<ul id="messageList"></ul>
<script>
function newEventSource() {
const sse = new EventSource('/path/to/sse');
let reconnectDelay = 1000;
sse.onmessage = (event) => {
console.log(event.data);
const messageList = document.querySelector('#messageList');
const li = document.createElement('li');
li.textContent = event.data;
messageList.appendChild(li);
}
sse.onopen = (event) => {
console.log('SSE 连接已经建立');
reconnectDelay = 1000;
}
sse.onerror = (event) => {
console.log('SSE 连接出错,' + reconnectDelay / 1000 + '秒后将尝试重新连接...');
sse.close();
setTimeout(() => {
sse = newEventSource();
reconnectDelay = reconnectDelay >= 30000 ? 30000 : reconnectDelay * 2;
}, reconnectDelay);
}
return sse;
}
let sse = newEventSource();
function checkSSEStatus(sse) {
setInterval(() => {
if (sse.readyState === EventSource.CLOSED) {
console.log('SSE 连接已经关闭,正在尝试重新连接...');
sse = newEventSource();
}
}, 3000);
}
checkSSEStatus(sse);
</script>
</body>
</html>关于如何实现 SSE 服务器端代码,在本文中不作详细介绍,需要读者自行查找相关资料。
学习意义和指导意义
本文介绍了如何实现 SSE 断线重连机制,这对于使用 SSE 实现实时消息推送的开发人员而言非常重要。本文提供了相关示例代码,可以直接应用于实际项目中。
另外,本文也提到了如何避免频繁重连对服务端造成不必要的压力,这是开发人员需要考虑的一个重要问题。
最后,本文针对 SSE 断线重连机制的实现方法,也提供了一些值得借鉴的思路和方法,可以用于类似的实时通信场景的开发工作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d7817aa941bf7134d75af2