Server-sent-events 造成的 HTTP 缓存坑

AI 编程助手,豆包旗下的编程助手,提供智能补全、智能预测、智能问答等能力,节省开发时间,释放脑海中的创造力,支持 VSCode,点击体验 AI

前端开发者们在设计基于 HTTP 协议的应用时,会经常遇到浏览器缓存问题。为了提高应用的性能,浏览器通常会缓存一些静态文件(如 JS、CSS 文件等),从而避免在后续访问中重复下载。然而,当我们使用 Server-sent-events 技术时,HTTP 缓存就会带来一些问题。

Server-sent-events

Server-sent-events(SSE),也称为 EventSource,是一种向客户端推送事件的技术。通过 SSE,服务器可以实时地向客户端发送事件和数据,而客户端则可以通过 JavaScript 进行监听和处理。SSE 基于 HTTP,使用的是长连接,因此可以实现实时的双向通信。

下面是一个 SSE 的基本示例:

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

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

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

在这个示例中,我们通过 EventSource 对象向 /sse 路径建立 SSE 连接。当服务器发送消息时,message 事件会被触发,此时我们可以通过 event.data 获取到服务器发送的数据。如果出现错误,error 事件会被触发。

HTTP 缓存

HTTP 缓存是指浏览器缓存一些静态资源,避免重复下载。HTTP 缓存的实现方式有两种:基于时间的缓存和基于内容的缓存。

基于时间的缓存是指浏览器在第一次请求某个资源时,会将Cache-ControlExpires 等头部信息保存下来,然后在后续访问时,仅当缓存过期或者不存在时才会重新下载。基于内容的缓存是指浏览器比较请求头部信息和响应头部信息中的 ETagLast-Modified 等信息,如果一致则表示资源未发生变化,可以直接从缓存中读取。

Server-sent-events 和 HTTP 缓存

SSE 本身并不会影响 HTTP 缓存,但是当使用了 HTTP 缓存时,SSE 发送的事件会被缓存,从而导致客户端无法实时接收到服务器的推送。

为了更好地理解这个问题,我们可以假设有一个 SSE 服务器不停地发送数字,客户端进行监听和显示。下面是使用基于时间的缓存的示例:

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

在这个示例中,我们使用 onload 事件调用 createEventSource() 函数建立 SSE 连接,当服务器发送消息时,我们使用 JavaScript 更新页面中的 data 元素。

现在我们来看一下 SSE 服务器代码:

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

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

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

这个服务器会不断地向客户端发送数字,每秒钟发一次。

假设我们现在在浏览器中打开这个页面,并启用基于时间的缓存。这时,我们在第一次打开页面时会发现数字正常地被更新。然而,如果你打开 DevTools,查看 Network 面板,你会发现 /sse 路径并没有被重新请求,也就是说,SSE 事件被缓存了。

现在,我们关闭浏览器,1 分钟后再打开页面,你会发现页面上的数字依然是上一次的数字。这是因为,虽然连接是实时的,但是由于使用了基于时间的缓存,浏览器仍然会从缓存中读取过期的数据。

解决方案

为了解决这个问题,我们需要做以下两点改进:

  1. 禁用 SSE 事件的缓存。
  2. 在 SSE 事件中添加一个唯一的标识符,来避免客户端接受到的事件被缓存。

为了禁用 SSE 事件的缓存,我们可以在服务器的响应头部信息中添加 Cache-Control: no-cachePragma: no-cache 等信息。这样浏览器就不会缓存这些事件了。在 Express 框架中,这个可以通过以下代码实现:

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

为了在 SSE 事件中添加一个唯一的标识符,我们可以使用 Date.now() 方法来生成一个随机数,然后把这个随机数放在 SSE 事件的数据中。这个随机数可以作为事件的标识符使用,避免客户端接受到的事件被缓存。

下面是改进后的 SSE 服务器代码:

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

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

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

在这个示例中,我们在 SSE 事件的数据中添加了一个随机数作为标识符。这样,浏览器就无法把这些事件缓存下来了。

结论

在使用 SSE 技术时,HTTP 缓存会给我们带来一些问题。通过禁用 SSE 事件的缓存,我们可以解决这个问题,并且通过添加唯一的标识符,我们可以避免客户端接受到的事件被缓存。在实际项目中,我们需要根据具体的应用场景和需求,决定是否使用 HTTP 缓存以及如何优化 SSE 技术的使用。

参考链接

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/671f4d452e7021665efce431


猜你喜欢

  • 最新的 JavaScript 标准 ECMAScript 2018(ES9)特性简介

    ECMAScript 2018(ES9)是 JavaScript 标准的最新版本,它于 2018 年 6 月正式发布。ES9 引入了一些新的特性,以帮助开发者更轻松地编写优质的 JavaScript ...

    11 天前
  • Jest 测试时如何使用 Snapshot 进行 UI 组件测试

    介绍 Jest 是一个流行的 JavaScript 测试框架,它被广泛用于前端开发,特别是在 React 生态系统中。Jest 提供了许多用于编写和执行测试的工具和库,其中一个重要的工具是 Snaps...

    11 天前
  • 如何让 Tailwind CSS 和 Material UI 共用?

    在现代 Web 开发中,前端框架的选择是非常关键的。其中,Tailwind CSS 和 Material UI 均为受欢迎的前端框架。虽然两者在 UI 设计和前端组件方面相似,但是它们之间的文档和使用...

    11 天前
  • Next.js 中集成 Redux 的最佳方案

    在 Next.js 中使用 Redux 的好处是,它可以让我们更方便地管理应用的状态。Redux 是一种可预测的状态管理器,可以在应用程序中能够帮助我们更好地管理状态。

    11 天前
  • jQuery 实现 SPA 的 3 个技巧

    单页面应用(Single Page Application,SPA)已经成为现代 Web 应用程序的主要形式。而 jQuery 作为一种流行的 JavaScript 库,提供了许多方便的方法来构建 S...

    11 天前
  • 如何在ECMAScript 2017 (ES8)中正确使用JavaScript类型注释

    随着JavaScript程序越来越复杂,类型验证和代码提示变得越来越受欢迎。此时,类型注释就成为了你必须掌握的知识之一。 在ECMAScript 2017 (ES8)中,JavaScript开始引入自...

    11 天前
  • 让 Web 文本不再困恼,响应式网页布局教程

    在当今时代,每天都有成千上万的用户通过互联网和其设备访问网站,这就要求我们在设计和开发网站时确保在所有屏幕大小和设备上都能够正常显示和操作。为了解决这个问题,响应式网页布局技术应运而生。

    11 天前
  • 如何对 Kubernetes 集群进行扩容?

    标题:Kubernetes集群扩容技巧 引言: Kubernetes作为云原生技术的代表之一,已经成为了现代容器化的重要组件。然而在实际的生产环境中,如何对Kubernetes集群进行扩容是每个运维工...

    11 天前
  • 如何在 GraphQL 中处理复杂的查询逻辑

    GraphQL 是一种现代的 API 查询语言,它允许客户端精确地指定请求的数据,减少了 over-fetching 和 under-fetching 的问题。但是,当用于处理复杂的查询逻辑时,Gra...

    11 天前
  • Redux-Saga 深入浅出:充分拿捏 React 项目数据流

    在 React 开发中,管理数据流一直是一个非常重要的部分。随着项目的逐渐扩大,简单的数据交互会逐渐变得复杂。Redux 是一个用于管理应用程序状态的可预测状态容器,可以轻松地解决这个问题。

    11 天前
  • Enzyme 测试 React 组件 props 的使用方法

    在开发 React 应用程序的过程中,我们经常需要测试组件的 props 是否按照预期工作。Enzyme 是一个流行的 JavaScript 测试实用程序,它提供了一些强大的工具来测试 React 组...

    11 天前
  • 如何解决 Hapi 框架中的内存泄漏问题

    随着 Hapi 框架的普及,越来越多的开发者在使用这个框架来开发 Web 应用程序。但是在实际应用中,经常会出现内存泄漏的问题,这会导致应用程序的性能下降,甚至崩溃。

    11 天前
  • 如何避免 MongoDB 数据偏移问题

    前言 MongoDB 是一个流行的文档数据库,常常用在前端应用中。但是,在使用 MongoDB 的过程中,可能会出现数据偏移问题。本文将会介绍 MongoDB 数据偏移问题的产生原因和如何避免这个问题...

    11 天前
  • TypeScript 中的命名空间使用及注意事项

    TypeScript 中的命名空间使用及注意事项 TypeScript 是一种开源的编程语言,它是 JavaScript 的超集,添加了可选的静态类型和其他一些语言特性。

    11 天前
  • Web Components 组件设计实践

    Web Components 是一种用于构建可复用组件的规范,它能帮助我们更好地组织代码,提高开发效率,同时也能使我们的项目更易于维护。在本文中,我们将分享一些如何设计可重用 UI 组件的实践经验,并...

    11 天前
  • LESS 实现响应式布局可用的方法探讨

    随着移动互联网的兴起,响应式布局越来越受到前端工程师的关注。在传统的 CSS 中实现响应式布局的方法有很多,但是在这篇文章中,我们将会着重讨论如何用 LESS 实现响应式布局,并且介绍一些实用的 LE...

    11 天前
  • 掌握 RESTful API 的数据安全与保护技巧

    前言 在当今社会互联网的普及下,API (Application Programming Interface) 的使用变得越发普遍,特别是 RESTful API ,其优雅的设计使开发人员得以很好地管...

    11 天前
  • RxJS 实现可撤销和恢复操作的方案

    RxJS 是一种流行的 JavaScript 库,它可以让你更方便地处理异步数据流。除了处理异步数据流,RxJS 还可以用来实现可撤销和恢复操作的方案。本篇文章将介绍如何使用 RxJS 实现可撤销和恢...

    11 天前
  • 构建高可用的 Custom Elements 组件库的方法与实践

    Custom Elements 是 Web 标准中一种新的规范,它允许开发者自定义 HTML 元素,从而实现组件化开发。Custom Elements 提供的组件化开发方式对于前端开发来说具有极高的灵...

    11 天前
  • 如何使用 Jest 测试 Angular 组件

    简介 Jest 是一个流行的 JavaScript 测试框架,可以用于测试前端和 Node.js 应用程序。在本文中,我们将探讨如何使用 Jest 测试 Angular 组件。

    11 天前

相关推荐

    暂无文章