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方法的一些简单描述,如有错误请各位大佬提出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值