SSE 库原理与源码分析

SSE(Server-Sent Events,又称为 EventSource)是一种浏览器与服务器之间的消息推送技术,它通过 HTTP 协议的长连接,实现了服务器端向客户端推送数据的能力。与 WebSocket 相比,SSE 更加轻量级和简单易用,可以在不需要双向通信的场景下,快速实现消息推送。

SSE 库原理

SSE 协议

SSE 协议是一种基于纯文本的协议,它以行为分割符,每行一条数据。需要注意的是,每条数据前必须加上 data:,并以两个回车符结束,否则浏览器不会解析。例如,一条简单的 SSE 数据如下:

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

SSE API

SSE API 是浏览器端实现 SSE 的接口,它通常由 XMLHttpRequest 对象封装,提供了如下三个方法:

  1. EventSource(url: string, options?: EventSourceInit): EventSource

    创建一个 EventSource 对象,参数 url 是 SSE 服务地址,options 是一个可选对象,包含如下属性:

    • withCredentials:是否携带跨域凭证。
    • headers:HTTP 请求头信息。
    • retryInterval:尝试重新连接的时间间隔,单位为毫秒,默认为 3000ms。
  2. EventSource.readyState: number

    返回连接状态,共有三种:

    • CONNECTING(0):连接正在建立。
    • OPEN(1):连接已经建立成功。
    • CLOSED(2):连接已经关闭。
  3. EventSource.onmessage: (event: MessageEvent) => void

    监听消息事件,当收到服务器推送的数据时,触发该回调函数。MessageEvent 中包含如下属性:

    • event.data:SSE 推送的数据。
    • event.lastEventId:上一次接收数据时,服务器发送的事件 ID。
    • event.origin:SSE 服务的域名或 IP 地址。
    • event.type:事件类型,默认为 message

SSE 优点

相比传统的轮询方法,SSE 有如下优点:

  1. 数据实时推送,延迟低。
  2. 服务器可通过数据 ID,标识每条数据,客户端可保证数据不丢失。
  3. 协议简单易用,兼容性较好。

SSE 库源码分析

SSE 主要代码

下面是一个简化版的 SSE 库实现,主要由以下三个部分组成:

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

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

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

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

SSE 类主要由四个方法组成:

  • 构造函数 constructor(url, options = {}):创建 SSE 类实例,初始化 SSE 服务地址和选项。
  • addEventListener(name, callback):监听事件,当收到服务器端推送的该类型消息时,触发回调函数。
  • connect():与 SSE 服务建立连接,创建 EventSource 对象并注册事件监听。
  • close():关闭 SSE 服务连接,清理监听事件。

构造函数中,传入 SSE 服务地址和选项。其中,选项包含如下属性:

  • headers:HTTP 请求头信息。
  • withCredentials:是否携带跨域凭证。
  • retryInterval:尝试重新连接的时间间隔,单位为毫秒,默认为 3000ms。

connect() 方法中,首先创建 EventSource 对象,并添加 openerrormessage 三种事件的监听。其中,message 事件的监听是必须的,因为它是 SSE 推送数据的主要入口。当接收到新的 SSE 消息时,会触发该事件回调 event

message 事件回调函数中,首先获取响应数据中的类型 type、数据 data 和上一次事件 ID lastEventId,然后根据 type 查找注册的回调函数,并调用其回调函数处理数据。

close() 方法中,首先判断 EventSource 是否存在,然后关闭连接并清理事件监听。

SSE 库示例代码

下面展示了如何使用 SSE 库实现消息推送。

服务端代码

对于 SSE 服务,无需特别设置,只需要使用标准的 HTTP 服务器即可。下面是一个使用 Node.js + Express 实现的 SSE 服务端示例:

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

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

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

服务端代码中,首先使用 express 创建一个 HTTP 服务器,然后设置响应头信息,保证浏览器能正常解析 SSE 响应。接着,每隔 1 秒钟向客户端推送一条当前时间的消息。

客户端代码

在客户端代码中,首先创建一个 SSE 对象并监听 message 事件。当收到服务端推送的数据时,将数据追加到页面上:

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

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

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

客户端代码主要有两个部分:HTML 页面和 JavaScript 代码。HTML 页面中定义了一个 ul 元素用于展示接收到的消息。JS 代码中,首先创建一个 SSE 对象,并监听 message 事件。当收到服务端推送的消息时,将消息添加到 messages 列表中。

总结

SSE 库是一种轻量级的浏览器与服务器之间的消息推送技术,它通过 HTTP 协议的长连接,实现了服务器端向客户端实时推送数据的能力。相比传统的轮询方法,SSE 延迟低、兼容性好、易用性高,是消息推送的良好解决方案。

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


猜你喜欢

  • Redis 高并发应用中的管道技术

    在 Redis 中,我们通常使用基于命令的操作来与 Redis 交互,每次执行一个 Redis 命令,都需要先发送给 Redis 服务器,等待 Redis 返回执行结果,这个过程会有网络开销和延迟,当...

    5 个月前
  • Web Components 包含 Blazor 与 Razor Components 的 ASP.NET Core 开发

    Web Components 是一种用于创建可重用的组件的技术,它能够让开发者设计出可扩展且易于维护的应用程序。随着 Web 技术的发展,Web Components 已经成为现代 Web 开发中不可...

    5 个月前
  • 如何使用 Fastify 框架实现文件上传下载

    前言 在 Web 应用中,文件上传下载是常见的需求之一。在使用 Node.js 开发 Web 应用时,我们可以使用不同的 Web 框架来实现这个功能。Fastify 是一个高效、低开销且可扩展的 We...

    5 个月前
  • 如何使用 LESS 进行 Iconfont 设计?

    在前端开发中,我们经常需要使用 Iconfont 来为网站添加图标和图形元素。Iconfont 是一种使用字体文件的方式来显示一些特定的图案的技术。在本文中,我们将介绍如何使用 LESS 进行 Ico...

    5 个月前
  • 使用 Kubernetes 部署单机应用时遇到的坑

    前言 Kubernetes 是一个自动化容器部署、自动扩展和管理的平台,为我们自动化部署和管理 Web 应用程序提供了非常大的帮助。但是,当你在使用 Kubernets 部署单机应用时,可能会遇到一些...

    5 个月前
  • 完整解读 GraphQL Query Language

    GraphQL 是一种用于 API 开发的查询语言,它的出现引起了前后端开发人员的广泛关注。GraphQL 具有高效、节省带宽等优点,亦可作为替代 RESTful API 的方案存在。

    5 个月前
  • 基于 PWA 技术的进阶 Web 开发

    随着移动设备的普及以及用户对 Web 应用的要求越来越高,PWA 成为了广受欢迎的新技术。PWA(Progressive Web App)是一种结合了 Web 技术和 Native 应用优秀体验的解决...

    5 个月前
  • 如何优雅地在 Serverless 架构中使用 MongoDB 数据库

    随着云计算技术的普及和新型架构的出现,Serverless 架构正逐渐成为互联网公司首选的开发模式。其中,MongoDB 数据库是 Serverless 架构中非常重要的一环。

    5 个月前
  • 在 Docker 容器内部部署 Redis 集群

    在现代化的应用程序开发中,分布式系统已经成为了一个主要的应用场景。分布式系统可以通过将部分工作负载分散到多台机器上,提高应用程序的可靠性、扩展性和性能。Redis 集群是一个流行的分布式解决方案,可以...

    5 个月前
  • SSE 连接超时问题:如何解决?

    在前端开发中,SSE(Server-Sent Events)作为一种服务器推送技术,可以实现服务器推送数据到客户端,以实现实时更新页面的效果。然而,有些开发者在使用 SSE 的过程中遇到了连接超时的问...

    5 个月前
  • 使用 Mocha 测试框架实现前端 A/B 测试

    什么是 A/B 测试? A/B 测试是一种通过比较不同版本的网站或应用程序来确定哪个版本效果更好的实验。通常,一些用户将看到版本 A,而另一些用户则看到版本 B。 在前端开发中,A/B 测试通常涉及更...

    5 个月前
  • ES12:深入解析依赖注入的实现方式

    依赖注入(Dependency Injection,DI)是一种广泛应用于开发领域的设计模式,主要用于降低代码之间的耦合性,提升代码的可维护性和可测试性。而在前端开发中,ES6 模块化的普及,也为我们...

    5 个月前
  • 使用 RxJS 实现 Vue 中非父子组件通讯

    简介 在 Vue 应用中,父组件向子组件传递数据是非常常见的操作。但是,当非父子组件之间需要通讯时,我们该如何实现呢?传统的做法是使用 Vuex 或者利用 event bus,但是这些方法会使代码更加...

    5 个月前
  • Deno 如何实现并发编程

    在现代 JavaScript 应用程序中,非阻塞 IO 和异步操作都是很重要的特性,这些特性就是因为并发模型被广泛使用。Deno 提供了一组高效的 API 来支持并发编程。

    5 个月前
  • 在 ECMAScript 2018 中手动实现 async/await

    前言 在 JavaScript 中,异步编程一直都是一项棘手的任务。早期,我们通常使用回调函数来处理异步操作,但这种方式很容易导致回调地狱,代码变得难以理解和维护。

    5 个月前
  • 在 Mocha 测试框架中模拟 React 组件的测试方案

    随着 React 技术的普及,前端开发中的测试方案也逐步向着更加完善的方向发展。Mocha 测试框架是目前比较流行的前端测试框架,本文将介绍在 Mocha 中如何模拟 React 组件进行测试,并提供...

    5 个月前
  • Sequelize 中创建新的字段到表格的方法

    Sequelize 是一个 Node.js 的 ORM(Object-Relational Mapping)框架,它可以让开发者直接使用 JavaScript 的语法操作数据库,而无需手写 SQL 语...

    5 个月前
  • Headless CMS 如何对大量数据进行管理

    在现代 Web 应用中,持续增长的内容和数据的规模以及多个设备和平台的支持,给内容管理系统 (CMS) 带来了巨大的挑战。传统的 CMS 都是 Monolithic Architecture,通常包括...

    5 个月前
  • MySQL 查询性能优化:使用合适的查询语句

    背景 MySQL 是一种常用的关系型数据库管理系统,被广泛应用于各种类型的应用程序。在实际应用中,我们经常需要使用查询语句来从数据库中获取数据。但是,在查询大量数据时,性能问题可能会成为瓶颈,影响整个...

    5 个月前
  • 如何使用 LESS 进行模块化设计?

    LESS 是一种 CSS 预处理器,它让 CSS 更加灵活和易于维护。它提供了很多新的语法和功能,比如变量、嵌套、Mixin、函数等,可以帮助我们更好地组织 CSS 代码。

    5 个月前

相关推荐

    暂无文章