SSE 如何在不同浏览器上正确兼容使用
SSE,即 Server-Sent Events,是一种在 web 应用程序中进行服务器推送事件的传输方式。它可以让我们实时地获取来自服务器的数据,而无需像 Ajax 一样需要不停地轮询。在前后端分离的现代化 web 应用程序中,SSE 成为了一种常用的技术手段。
但是,SSE 的兼容性,并不像我们想象中那么完美。在不同的浏览器中,SSE 的实现可能是不同的,这就导致了在某些情况下,我们难以正确地实现 SSE 的兼容性。
下面我们将了解 SSE 在不同浏览器中正确兼容使用的方法。
SSE 简介
在介绍 SSE 的兼容性问题前,我们先来了解一下 SSE 的使用。
SSE 可以让浏览器与服务器建立单向连接,服务器可以随时将消息推送给浏览器。这样浏览器就可以实时地接收服务器端的数据。
在客户端,我们可以使用 JavaScript 的 EventSource
对象来建立 SSE 连接,如下所示:
const eventSource = new EventSource('/events'); eventSource.onmessage = function(event) { console.log(event.data); };
这样,当服务器向 /events
发送数据时,事件源 eventSource
就可以接收到数据并打印到控制台上。
而在服务器端,SSE 的实现比较简单。我们只需要在响应中添加一些特定的 HTTP 响应头即可,如下所示:
HTTP/1.1 200 OK Content-Type: text-event-stream Cache-Control: no-cache Connection: keep-alive data: first\n\n data: second\n\n
在 SSE 中,有一些特殊的 HTTP 响应头需要注意:
Content-Type: text-event-stream
:告诉浏览器,这是一种 SSE 数据流。Cache-Control: no-cache
:告诉浏览器,不要缓存这个响应。Connection: keep-alive
:告诉服务器,保持连接状态,以便服务器可以推送更多的数据。
在响应体中,我们可以使用 data
字段来设置需要推送的数据。每个数据都以 data:
开头,并以两个连续的换行符 \n\n
结尾。
兼容性问题
SSE 的实现看上去很简单,但是在不同浏览器中,SSE 的行为可能是不同的,这就给我们的兼容性带来了一些问题。
Safari 和 IE
在 Safari 和 IE 中,EventSource 的默认参数中的 withCredentials 属性默认为 false,这意味着我们不能使用 SSE 向跨域的服务器发送请求(也就是 CORS 问题)。如果要实现跨域 SSE,我们需要将 withCredentials 设置为 true,如下所示:
const eventSource = new EventSource('http://example.com/sse', { withCredentials: true });
Chrome
在 Chrome 中,SSE 最多只能同时建立六个 SSE 连接。我们可以通过以下方式解决这个问题:
- 利用同一 SSE 连接推送多个消息;
- 使用多个域名或子域名,来建立多个 SSE 连接;
- 使用 WebSocket 来代替 SSE。
Firefox
在 Firefox 中,SSE 的事件源对象 EventSource
对象的 onerror
事件不能正确地处理错误。如果出现错误,onerror
事件会被触发,但是浏览器会自动重试 SSE 连接,而不是关闭 SSE 连接并显示错误消息。我们可以通过以下方式解决这个问题:
- 在服务器端,向 SSE 数据中添加一个
heartbeat
消息,在 dat 后面添加一行:
,这样浏览器就可以识别服务器是否在线; - 在客户端,如果收到了
heartbeat
消息,则表示服务器还活着;否则表示服务器已经挂掉了。
Edge
在 Edge 中,SSE 的默认缓存时间为 5 秒。如果在 5 秒内没有收到来自服务器的数据,则 Edge 会自动关闭连接。我们可以通过以下方式解决这个问题:
- 在服务器端,定时向 SSE 数据流中推送一个
:
,来维持 SSE 连接; - 在客户端,检查 SSE 连接是否被关闭,如果被关闭,则自动重新建立连接。
总结
SSE 作为一种构建实时 web 应用程序的技术,其兼容性问题需要我们格外注意。不同的浏览器对 SSE 的实现方式是不同的,我们需要了解各个浏览器的具体情况,才能更好地解决 SSE 的兼容性问题。
当我们遇到 SSE 的兼容性问题时,我们可以通过相应的方法来解决这些问题。只有正确地解决了兼容性问题,我们才能更好地在 web 应用程序中使用 SSE。
示例代码:
服务器端,使用 Node.js + express:
-- -------------------- ---- ------- ------------------ ------------- ---- - -------------------------- --------------------- --------------------------- ------------ ------------------------ -------------- ---------------------- - ---------------- - - ---------- - -------- -- ---- - --- ---------------- ---------------- ------------ --------------- ---------- - ---------------- ---------- --------- --- ---
客户端:
-- -------------------- ---- ------- ----- ----------- - --- ----------------------- ------------------ - ---------- - ---------------- ---------- -------------- -- --------------------- - --------------- - ------------------------ -- ------------------- - ----------- - ---------------- ---------- --------- --
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64e30ffbf6b2d6eab3e67043