SSE 如何在不同浏览器上正确兼容使用

阅读时长 5 分钟读完

SSE 如何在不同浏览器上正确兼容使用

SSE,即 Server-Sent Events,是一种在 web 应用程序中进行服务器推送事件的传输方式。它可以让我们实时地获取来自服务器的数据,而无需像 Ajax 一样需要不停地轮询。在前后端分离的现代化 web 应用程序中,SSE 成为了一种常用的技术手段。

但是,SSE 的兼容性,并不像我们想象中那么完美。在不同的浏览器中,SSE 的实现可能是不同的,这就导致了在某些情况下,我们难以正确地实现 SSE 的兼容性。

下面我们将了解 SSE 在不同浏览器中正确兼容使用的方法。

SSE 简介

在介绍 SSE 的兼容性问题前,我们先来了解一下 SSE 的使用。

SSE 可以让浏览器与服务器建立单向连接,服务器可以随时将消息推送给浏览器。这样浏览器就可以实时地接收服务器端的数据。

在客户端,我们可以使用 JavaScript 的 EventSource 对象来建立 SSE 连接,如下所示:

这样,当服务器向 /events 发送数据时,事件源 eventSource 就可以接收到数据并打印到控制台上。

而在服务器端,SSE 的实现比较简单。我们只需要在响应中添加一些特定的 HTTP 响应头即可,如下所示:

在 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,如下所示:

Chrome

在 Chrome 中,SSE 最多只能同时建立六个 SSE 连接。我们可以通过以下方式解决这个问题:

  1. 利用同一 SSE 连接推送多个消息;
  2. 使用多个域名或子域名,来建立多个 SSE 连接;
  3. 使用 WebSocket 来代替 SSE。

Firefox

在 Firefox 中,SSE 的事件源对象 EventSource 对象的 onerror 事件不能正确地处理错误。如果出现错误,onerror 事件会被触发,但是浏览器会自动重试 SSE 连接,而不是关闭 SSE 连接并显示错误消息。我们可以通过以下方式解决这个问题:

  1. 在服务器端,向 SSE 数据中添加一个 heartbeat 消息,在 dat 后面添加一行 :,这样浏览器就可以识别服务器是否在线;
  2. 在客户端,如果收到了 heartbeat 消息,则表示服务器还活着;否则表示服务器已经挂掉了。

Edge

在 Edge 中,SSE 的默认缓存时间为 5 秒。如果在 5 秒内没有收到来自服务器的数据,则 Edge 会自动关闭连接。我们可以通过以下方式解决这个问题:

  1. 在服务器端,定时向 SSE 数据流中推送一个 :,来维持 SSE 连接;
  2. 在客户端,检查 SSE 连接是否被关闭,如果被关闭,则自动重新建立连接。

总结

SSE 作为一种构建实时 web 应用程序的技术,其兼容性问题需要我们格外注意。不同的浏览器对 SSE 的实现方式是不同的,我们需要了解各个浏览器的具体情况,才能更好地解决 SSE 的兼容性问题。

当我们遇到 SSE 的兼容性问题时,我们可以通过相应的方法来解决这些问题。只有正确地解决了兼容性问题,我们才能更好地在 web 应用程序中使用 SSE。

示例代码:

服务器端,使用 Node.js + express:

-- -------------------- ---- -------
------------------ ------------- ---- -
  -------------------------- ---------------------
  --------------------------- ------------
  ------------------------ --------------
  
  ---------------------- -
    ---------------- - - ---------- - --------
  -- ---- - ---
  
  ---------------- ----------------
  ------------
  --------------- ---------- -
    ---------------- ---------- ---------
  ---
---

客户端:

-- -------------------- ---- -------
----- ----------- - --- -----------------------
------------------ - ---------- -
  ---------------- ---------- --------------
--
--------------------- - --------------- -
  ------------------------
--
------------------- - ----------- -
  ---------------- ---------- ---------
--

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64e30ffbf6b2d6eab3e67043

纠错
反馈