解决 Firefox 上 Server-Sent Events 问题的方案
Server-Sent Events(以下简称 SSE)是一种比传统的轮询技术更加高效的实时通信方式,能够将服务器端发送的消息推送到客户端。但是,当我们在 Firefox 上使用 SSE 时,可能会遭遇以下奇怪问题:
- 进入页面后,无法接收到 SSE 事件,但是一旦刷新页面,就可以正常接收事件
- 尽管 SSE 事件已经停止,但是 Firefox 仍然在持续不断地向服务器发送请求
本文将为读者介绍如何解决上述问题,并给出具体的实现方案和示例代码。
问题分析
首先来分析一下上述问题的成因。在 SSE 中,浏览器通过向服务器发送 HTTP 请求,并在 HTTP 头部中添加 Accept: text/event-stream
和 Cache-Control: no-cache
等字段的方式来发起 SSE 事件订阅。但是,在 Firefox 上,这些请求会被本地缓存拦截掉,从而导致 SSE 事件无法正常推送到客户端。
那么问题来了:为什么刷新一下页面就可以正常接收 SSE 事件呢?这是因为刷新页面会导致 Firefox 清空本地缓存,从而使得浏览器能够正常发起 SSE 请求,从而接收事件。
接下来,我们再来看一下 Firefox 持续发送请求的问题。这是因为 Firefox 会自动重试之前失败的 SSE 请求,而这些请求在之前因为缓存问题而失败了。因此,我们需要在服务器端对这些请求进行过滤,只返回最新的 SSE 数据,而不是之前已经结束的事件数据。
解决方案
在以上分析的基础上,我们可以采用以下方案解决 Firefox 上 SSE 的问题:
- 在 SSE 请求路径中添加随机参数,避免浏览器缓存请求。例如:
const source = new EventSource(`/sse?_=${Math.random()}`);
- 在服务器端对 SSE 请求进行过滤,只返回最新的 SSE 数据。例如:
-- -------------------- ---- ------- -- ----------- --- -- -- -- ---------- ---- --- ------- --------------------- --------------- -------------------- ---------------- ----------- ------------- ------------- --- ---------------- ------------------------------------ ---------- - -----展开代码
完整代码
下面是一份基于 Express.js 的 SSE 示例代码:
服务器端代码
-- -------------------- ---- ------- ----- ------- - ------------------- ----- --- - ---------- --- ---------- - ----- --------------- ----- ---- -- - --------------------- --------------- -------------------- ---------------- ----------- ------------- ------------- --- ----- -------- - ----------- ----- ------------ - -------------- -- - -- --- ---- --- --- ------- ------------ ----------- -- ------- ----- ------------ - -------------- -- - -- -- --- -- ---------------- ------------------------------------ ---------- - ----- -- ------ --------------- -- -- - ---------------------------- ---------------------------- ---------------- ------ ----------- ------ -------------- --- --- ------------------ -------------------- --------- ----- --- ----- ---- -- - --------------------- ------ -------------- ---------- - --------- -------------------- --- ---------------- -- -- - ------------------- -- --------- -- ---- -------- ---展开代码
客户端代码
const source = new EventSource(`/sse?_=${Math.random()}`); source.onmessage = (event) => { console.log(`Received SSE data: ${event.data}`); };
指导意义
本文解决了 Firefox 上 SSE 事件无法接收和持续发送请求的问题,也给出了具体实现方案和示例代码。在实际开发中,我们可以按照上述方案对 SSE 进行优化,提高实时通信的效率和稳定性。
此外,本文还提供了一些工具和库,可以帮助我们更加方便地使用 SSE 技术,例如:
- EventSource polyfill:为不支持 SSE 的浏览器提供支持
- express-sse:在 Express.js 中更方便地实现 SSE
最后,希望本文能够对前端开发者们有所启发和帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67802b14ce7f4861252fdc26