前言
SSE (Server-Sent Events) 是一种服务器向客户端推送事件的机制,它基于 HTTP 协议,但相比于长轮询和 Websocket,它具有更轻量的通信开销和更简单的协议实现。因此,它在 web 开发中得到了广泛的应用。
然而,如果你在使用 SSE 时遇到了 Chrome 浏览器自动断开 SSE 连接的问题,那么在本文中,我将详细介绍这个问题的原因和解决方法,并带给你实际代码的示例。
问题描述
在使用 SSE 时,我们通常会创建一个 EventSource 对象,然后通过 onmessage 事件监听 SSE 服务器发来的消息。
const source = new EventSource('/sse-server'); source.onmessage = function(event) { console.log('收到事件:', event); };
然而,在 Chrome 浏览器下,有时候这个连接会在没有与服务器主动断开的情况下自动中断,出现长时间没有数据推送的断开状态:
这是什么原因呢?如何解决呢?
问题原因
要解决这个问题,我们首先需要了解它的原因。在 Chrome 浏览器下,SSE 连接有时候会自动中断,通常是因为以下两个原因:
服务端发送的消息过长。在 Chrome 浏览器下,如果服务端发送的消息长度超过 16KB,那么就会触发自动中断 SSE 连接的机制,此时需要通过拆分消息来绕过这个限制。
超过 30 秒没有接收到数据。在 Chrome 浏览器下,如果 SSE 连接在 30 秒内没有接收到任何数据,那么就会自动中断,此时需要通过心跳机制来保持连接。
解决方法
拆分消息
对于第一个问题,我们可以通过拆分消息来绕过 16KB 的限制。通常,这个限制往往是由服务端所决定的,因此我们需要在服务端拆分消息并发送多个小段的消息,让客户端能够正确地处理这些消息。
以下是一个示例代码,它将一个长字符串拆分成多个小段并发送:
-- -------------------- ---- ------- -- --------- ----- ------- - ------------------- ----- --- - ---------- -- --------- ----- ------------ - -- -- - ------ ------------------------------------ ---- -- -- ----------------- ---------------------- ----- ---- -- - ----- --------- - -------------------------------------------- -- ---------------------- --- ----- ---------- - ----- ----- ------ - ------------------- ---------------------------- ------ ----------------------------- ------------------- ---------------- -- -------- ---------------------- ------ -- - ----- -- - ----- - -- ----- ----- - ---------- -------------- ---------- ----------------- ------------- ---------------- ------------- ---------------- --- ---------- --- ---------------- -- -- - ---------------- -------- ---
在客户端,我们需要对拆分后的多个小段消息进行合并,以得到最终的完整消息:
-- -------------------- ---- ------- -- --------- ----- ------ - --- --------------------------- --- ------ - --- ---------------- - --------------- - ----- ---- - ----------- ------------------ -- ------------- -- ------------------------------------------- - ----- ------- - ---------------- -------------------- --------- ------ - --- - --
需要注意的是,我们在 server.js 文件中使用了 id
和 event
字段来标识 SSE 的消息类型和消息序号,并在客户端代码中使用 event.lastEventId
来判断当前是否已经接收到最后一个消息段。
心跳机制
对于第二个问题,我们可以通过心跳机制来保持连接活性。通常,我们可以在 SSE 连接的 onopen
回调函数中定时发送一个“心跳”消息,以维持与服务器的连接。代码如下:
-- -------------------- ---- ------- ----- ------ - --- --------------------------- --- --------- - ----- ------------- - ---------- - ---------------- -------- -- -- ----------- ----- -- ----- --------- - ---------------------- - ------------------------- -- ------- -- -------------- - ---------- - ---------------- -------- ------------------------- --
这里的 setInterval
函数将会每隔 20 秒向服务器发送一个心跳消息,如果 30 秒内没有接收到任何消息,则 SSE 连接会被自动中断。
总结
通过以上方法,我们可以解决在 Chrome 浏览器下 SSE 自动中断连接的问题。需要注意的是,由于服务器和客户端可能存在时钟不同步的情况,建议在实现心跳机制时,采用时间戳进行校验,以避免不同步导致的问题。
此外,在使用 SSE 时,也应该注意控制发送的消息长度,以免触发浏览器的自动中断机制,从而达到更加稳定的连接效果。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64c9021e5ad90b6d04155d8b