SSE单向通讯的长连接

前言

在前端开发中,少不了数据实时更新的情况,一般来说常用的方式以下两种。

1.轮询
2.websocket

但是都有比较大的问题,轮询每次都要建立一次tcp连接,消耗性能,且会占用请求限制;
websocket支持双向通信协议,功能更加全面,这就意味着负担比较大,俗称重;
而开发过程中可能会出现我只想需要服务端给我发送数据不需要客户端向服务端发送的情况,这时就请出我们文章标题中所说的技术SSE

一、SSE是什么?

SSE(Server-Sent Events,服务器发送事件)是一种由服务器向浏览器单向推送更新的技术。通过 SSE,服务器可以持续不断地向客户端发送数据,而客户端通过 EventSource 接口接收这些数据

  • 单向通信:服务器向客户端推送数据,客户端无法向服务器发送数据。
  • 自动重连:如果连接中断,浏览器会自动尝试重新连接。

二、使用步骤

废话不多说,直接上代码
后端:(node)

const http = require("http");

const server = http.createServer();

server.on("request", (req, res) => {
  if (req.url === "/sse") {
    try {
        res.writeHead(200, {
            "Content-Type": "text/event-stream",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "Access-Control-Allow-Origin": "*",
          });
          // 发送初始事件
          res.write("event: init\ndata: Hello, client!\n\n");
          // 模拟定时发送事件
          const intervalId = setInterval(() => {
            res.write("data: " + new Date().toLocaleTimeString() + "\n\n");
          }, 1000);
          // 监听客户端断开连接事件
          req.on("close", () => {
            clearInterval(intervalId);
          });
    } catch (error) {
      console.log(error);
    }
  } else {
    res.writeHead(404);
    res.end();
  }
});

server.listen(3000, () => {
  console.log("\x1b[36m%s\x1b[0m", "{^_^} 启动成功了哦!");
});

后端使用node编写,需要注意设置头部属性

前端代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="onConnect">断开连接</button>
    <script>
        window.onload = function () {
            let eventSource = null
            if (window.EventSource) {
                eventSource = new EventSource('http://localhost:3000/sse')
                eventSource.onopen = function (event) {
                    console.log("连接成功", event)
                }
                // 无法直接区分手动关闭和连接失败  通过一个变量来识别
                eventSource.onerror = function (event) {
                    console.log("连接失败")
                    // 重新连接
                    // if (event.readyState == EventSource.CLOSED) {
                    //     eventSource = new EventSource('http://localhost:3000/sse')
                    // }
                }
                eventSource.onmessage = function (event) {
                    console.log(event.data)
                }
                eventSource.onclose = function (event) {
                    console.log("连接关闭")
                }

            } else {
                throw new Error("当前浏览器不支持SSE")
            }
            let onConnect = document.getElementById("onConnect")
            onConnect.onclick = function () {
                // 主动断开连接
                eventSource.close()
            }

        }
    </script>
</body>

</html>

注意点:

  1. 由于SSE是服务端向客户端发送,所以前端的SSE事件没有send事件,其他基本一致
  2. 浏览器针对SSE是有异常断开重连机制的,当服务端关闭时,浏览器会自动出发重连在这里插入图片描述
    如果调用close的话,浏览器是不会去发出重连的;
  3. 重连机制无法修改最大次数,但是可以通过onerror事件实现该方法 改造最大次数重连之后的页面

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="onConnect">断开连接</button>
    <script>
        window.onload = function () {
            const maxReconnectAttempts = 5
            let reconnectAttempts = 0
            let eventSource = null
           
            let onConnect = document.getElementById("onConnect")
            onConnect.onclick = function () {
                // 主动断开连接
                eventSource.close()
            }
            const connect = function () {
                eventSource = new EventSource('http://localhost:3000/sse')
                eventSource.onopen = function (event) {
                    console.log("连接成功", event)
                }
                // 无法直接区分手动关闭和连接失败  通过一个变量来识别
                eventSource.onerror = function (event) {
                    console.log("连接失败")
                    eventSource.close()
                    if (reconnectAttempts < maxReconnectAttempts) {
                        reconnectAttempts++;
                        connect();
                } else {
                    console.log("达到最大重连次数,停止尝试。");
                }
                }
                eventSource.onmessage = function (event) {
                    console.log(event.data)
                }
                eventSource.onclose = function (event) {
                    console.log("连接关闭")
                }

            }

            if (window.EventSource) {
                connect()

            } else {
                throw new Error("当前浏览器不支持SSE")
            }
        }
    </script>
</body>

</html>

总结

以上就是针对SSE方法的一些简单描述,如有错误请各位大佬提出

<think>好的,我现在要回答用户关于如何在Vue中实现SSE连接的问题。首先,我需要回顾一下用户提供的引用内容,特别是引用[3]提到了Spring Boot和Vue结合使用SSE的情况,其中提到了一些注意事项,比如处理断开连接、持久连接的管理以及资源消耗的问题。这些信息对于编写前端代码时的错误处理可能会有帮助。 用户需要的是Vue中的实现教程和示例代码。首先,我应该考虑如何在Vue组件中正确使用EventSource API。EventSource是浏览器原生支持的SSE客户端,所以不需要额外安装库。但需要注意兼容性问题,不过现代浏览器基本都支持。 接下来,步骤应该包括:创建EventSource实例,监听不同的事件(如message、open、error),处理数据更新,并在组件销毁时关闭连接以避免内存泄漏。引用[3]中提到的断开连接处理,比如捕获异常和调用complete方法,这在后端处理,但前端也需要处理error事件和关闭事件,可能需要重连机制。 示例代码方面,应该在Vue的mounted生命周期钩子中建立连接,并在beforeUnmount中关闭。同时,数据接收后如何更新组件状态,比如使用Vue的响应式数据(data属性或ref)。 另外,用户可能需要知道如何自定义事件类型,而不仅仅是默认的message事件,所以需要提到addEventListener的方法。同时,错误处理和连接状态的管理也很重要,比如显示连接状态给用户。 最后,根据用户的要求生成相关问题,这些问题应该围绕SSE在Vue中的高级用法、优化、对比其他技术等方面。 需要确保回答结构清晰,分步骤说明,并提供可运行的代码示例。同时,引用相关的引用内容,特别是引用[3]提到的异常处理和资源管理,虽然主要在后端,但前端也需要对应处理,比如错误监听和重连。</think>### Vue中实现Server-Sent Events (SSE)连接的步骤 #### 一、基础实现 1. **创建EventSource对象** 在Vue组件中通过浏览器原生`EventSource` API建立SSE连接: ```javascript mounted() { // 创建SSE连接 this.eventSource = new EventSource('http://your-api/sse-endpoint'); // 监听消息事件 this.eventSource.onmessage = (event) => { this.sseData = JSON.parse(event.data); }; // 自定义事件类型 this.eventSource.addEventListener('customEvent', (e) => { console.log('自定义事件:', e.data); }); } ``` 2. **处理连接状态** ```javascript // 连接打开时触发 this.eventSource.onopen = () => { this.connectionStatus = '已连接'; }; // 错误处理(包括连接中断) this.eventSource.onerror = (err) => { console.error('SSE错误:', err); this.connectionStatus = '连接异常'; this.eventSource.close(); // 主动关闭连接[^3] }; ``` 3. **组件销毁时关闭连接** ```javascript beforeUnmount() { if (this.eventSource) { this.eventSource.close(); console.log('SSE连接已关闭'); } } ``` #### 二、完整示例代码 ```vue <template> <div> <p>连接状态: {{ connectionStatus }}</p> <div v-if="sseData"> <p>实时数据: {{ sseData }}</p> </div> </div> </template> <script> export default { data() { return { eventSource: null, sseData: null, connectionStatus: '连接中...' } }, mounted() { this.connectSSE(); }, methods: { connectSSE() { // 创建SSE连接 this.eventSource = new EventSource('/api/sse'); // 监听标准消息 this.eventSource.onmessage = (e) => { try { this.sseData = JSON.parse(e.data); } catch (err) { console.error('数据解析失败:', err); } }; // 监听自定义事件 this.eventSource.addEventListener('status_update', (e) => { console.log('状态更新:', e.data); }); // 连接状态处理 this.eventSource.onopen = () => { this.connectionStatus = '已连接'; }; this.eventSource.onerror = (err) => { console.error('连接异常:', err); this.connectionStatus = '断开连接'; this.reconnect(); // 实现自动重连 }; }, reconnect() { setTimeout(() => { console.log('尝试重新连接...'); this.connectSSE(); }, 3000); } }, beforeUnmount() { if (this.eventSource) { this.eventSource.close(); this.connectionStatus = '已断开'; } } } </script> ``` #### 三、关键注意事项 1. **跨域问题**:若后端API与前端不同源,需配置CORS: ```java // Spring Boot后端示例 @CrossOrigin(origins = "http://your-vue-domain") @GetMapping("/sse") public SseEmitter createConnection() { // ... } ``` 2. **心跳机制**:为防止连接超时,建议后端定期发送空注释: ```text : heartbeat\n\n ``` 3. **错误恢复**:通过`onerror`事件实现自动重连,如示例中的`reconnect()`方法 4. **数据格式**:推荐使用JSON进行结构化数据传输: ```javascript // 后端发送格式 data: {"time": "2023-07-20", "value": 42}\n\n ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值