一.什么是SSE

        SSE协议是一种基于http协议的单向通信协议,服务端可以向客户端发送数据,但是客户端不能向服务器发送数据。客户端通过创建一个到服务器的单向连接来监听事件。可以将一次性返回数据包改为流式返回数据。SSE协议支持断线重连,也支持自定义响应事件。比如ChatGpt使用的通信方式就是SSE协议,相比于websocket通信这是一个更为轻量级的通信方式,使用方法简单。但是在浏览器原生的EventSource不支持设置请求头,需要借助第三方包去实现,同时也需要后端设置接口的响应头Content-Type:text/event-stream

二.SSE和WebSocket的区别

        WebSocket  API

           WebSocket是基于TCP协议的一种用于应用层的网络协议,它实现了浏览器与服务器之间的全双工通信,它允许服务器主动发信息给客户端。所以,浏览器和服务器只需要完成一次握手就可以建立持久性的连接,并且能够实现双向数据传输。

        特点:

          1.传输的数据格式可以是文本也可以是二进制形式

          2.不受同源策略的限制,可以与任意服务端进行通信

          3.兼容HTTP协议,默认端口同样是80(ws)和443(ws)

          4.客户端和服务端通信时开销较少,与HTTP协议不同,不需要每次都携带完整的头部信息

          5.若在通信过程中连接中断,需要自己实现断线重连

        区别:

          1.sse协议仅支持服务端向客户端发送数据,而websocket支持双向通信,服务端和客户端之间可以互相通信

          2.sse是一种轻量级的通信协议,而websocket整体的一些方法事件较为复杂

          3.sse支持断线重连机制,而websocket需要自己实现断线重连

          4.sse是基于HTTP协议的通信协议,而websocket是基于TCP协议的网络层通信协议

三.前端使用SSE

 <h1>fetchSSE Demo</h1>
    <button onclick="connectFetch()">建立 fetchSSE 连接</button>
    <button onclick="closeSSE()">断开 fetchSSE 连接</button>
    <br />
    <br />
    <div id="message"></div>
    <script>
        const messageElement = document.getElementById('message')
        let controller = null
        // 建立 FETCH-SSE 连接
        const connectFetch = () => {
            controller = new AbortController()
            fetchEventSource('http://127.0.0.1:3001/fetch-sse', {
                method: 'POST',
                body: JSON.stringify({
                    content: 'xxx'
                }),
                signal: controller.signal,
                onopen: () => {
                    messageElement.innerHTML += `FETCH 连接成功<br />`
                },
                onclose: () => {
                    messageElement.innerHTML += `FETCH 连接关闭<br />`
                },
                onmessage: (event) => {
                    const data = JSON.parse(event)
                    messageElement.innerHTML += `${data.id} --- ${data.time} --- body参数:${JSON.stringify(data.body)}` + '<br />'
                },
                onerror: (e) => {
                    console.log(e)
                }
            })
        }

        // 断开 FETCH-SSE 连接
        const closeSSE = () => {
            if (controller) {
                controller.abort()
                controller = undefined
                messageElement.innerHTML += `FETCH 连接关闭<br />`
            }
        }
        const fetchEventSource = (url, options) => {
            fetch(url, options)
                .then(response => {
                    if (response.status === 200) {
                        options.onopen && options.onopen()
                        return response.body
                    }
                })
                .then(rb => {
                    const reader = rb.getReader()
                    const push = () => {
                        // done 为数据流是否接收完成,boolean
                        // value 为返回数据,Uint8Array
                        return reader.read().then(({ done, value }) => {
                            if (done) {
                                options.onclose && options.onclose()
                                return
                            }
                            options.onmessage && options.onmessage(new TextDecoder().decode(value))
                            // 持续读取流信息
                            return push()
                        })
                    }
                    // 开始读取流信息
                    return push()
                })
                .catch((e) => {
                    options.error && options.error(e)
                })
        }

        

        
        

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐