解决 Chrome 浏览器下 SSE 自动中断连接的问题

前言

SSE (Server-Sent Events) 是一种服务器向客户端推送事件的机制,它基于 HTTP 协议,但相比于长轮询和 Websocket,它具有更轻量的通信开销和更简单的协议实现。因此,它在 web 开发中得到了广泛的应用。

然而,如果你在使用 SSE 时遇到了 Chrome 浏览器自动断开 SSE 连接的问题,那么在本文中,我将详细介绍这个问题的原因和解决方法,并带给你实际代码的示例。

问题描述

在使用 SSE 时,我们通常会创建一个 EventSource 对象,然后通过 onmessage 事件监听 SSE 服务器发来的消息。

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

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

然而,在 Chrome 浏览器下,有时候这个连接会在没有与服务器主动断开的情况下自动中断,出现长时间没有数据推送的断开状态:

这是什么原因呢?如何解决呢?

问题原因

要解决这个问题,我们首先需要了解它的原因。在 Chrome 浏览器下,SSE 连接有时候会自动中断,通常是因为以下两个原因:

  1. 服务端发送的消息过长。在 Chrome 浏览器下,如果服务端发送的消息长度超过 16KB,那么就会触发自动中断 SSE 连接的机制,此时需要通过拆分消息来绕过这个限制。

  2. 超过 30 秒没有接收到数据。在 Chrome 浏览器下,如果 SSE 连接在 30 秒内没有接收到任何数据,那么就会自动中断,此时需要通过心跳机制来保持连接。

解决方法

拆分消息

对于第一个问题,我们可以通过拆分消息来绕过 16KB 的限制。通常,这个限制往往是由服务端所决定的,因此我们需要在服务端拆分消息并发送多个小段的消息,让客户端能够正确地处理这些消息。

以下是一个示例代码,它将一个长字符串拆分成多个小段并发送:

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

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

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

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

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

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

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

在客户端,我们需要对拆分后的多个小段消息进行合并,以得到最终的完整消息:

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

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

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

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

需要注意的是,我们在 server.js 文件中使用了 idevent 字段来标识 SSE 的消息类型和消息序号,并在客户端代码中使用 event.lastEventId 来判断当前是否已经接收到最后一个消息段。

心跳机制

对于第二个问题,我们可以通过心跳机制来保持连接活性。通常,我们可以在 SSE 连接的 onopen 回调函数中定时发送一个“心跳”消息,以维持与服务器的连接。代码如下:

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

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

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

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

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

这里的 setInterval 函数将会每隔 20 秒向服务器发送一个心跳消息,如果 30 秒内没有接收到任何消息,则 SSE 连接会被自动中断。

总结

通过以上方法,我们可以解决在 Chrome 浏览器下 SSE 自动中断连接的问题。需要注意的是,由于服务器和客户端可能存在时钟不同步的情况,建议在实现心跳机制时,采用时间戳进行校验,以避免不同步导致的问题。

此外,在使用 SSE 时,也应该注意控制发送的消息长度,以免触发浏览器的自动中断机制,从而达到更加稳定的连接效果。

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


猜你喜欢

  • React 中统一管理接口地址的方案分享

    前端开发中,调用接口是非常常见的操作。在 React 项目中,我们通常需要把接口地址存放在一个统一的地方,便于维护和管理。本文将介绍一种方便的方式来管理接口地址,并对该方案进行详细的讲解和说明。

    1 年前
  • 使用 Vue.js 和 WebRTC 构建音视频通信应用

    前言 音视频通信已经成为当今互联网应用的重要组成部分。WebRTC 是一种 Web 实时通信技术,它允许浏览器和移动平台应用程序实现实时通信和音视频会议。本文将讲解使用 Vue.js 和 WebRTC...

    1 年前
  • Cypress 测试:如何处理无 UI 场景下的 API 测试

    业务场景中,API 测试不可或缺。一些不允许直接运行或者需要特殊环境配置的依赖,例如它们只能在某个特定时间运行或者需要进行特定的资源部署等。为了避免代码和测试之间的耦合,很多测试人员喜欢用代码分离测试...

    1 年前
  • Gatsby.js 和 Sanity 的 Headless CMS 联动:更好的开发体验与数据管理

    前言 在现代 Web 开发中,前端框架和 Headless CMS 的结合已经成为了一种趋势。这种结合可以提升开发效率、降低维护成本、提高网站的性能和体验等。 Gatsby.js 是一款基于 Reac...

    1 年前
  • SASS 中的媒体查询注意事项与优化方案

    SASS 中的媒体查询注意事项与优化方案 前端开发中,响应式布局相当重要。而响应式布局中,媒体查询是不可或缺的一部分。媒体查询可以使元素在不同的设备上展现不同的样式。

    1 年前
  • SSE 实现时的容错处理方法详解

    随着 Web 应用的不断发展,实时通信变得越来越重要。SSE(Server Sent Events)是一种实现实时通信的技术,它允许服务器向客户端推送数据,同时也提供了一些容错机制以确保通信的可靠性。

    1 年前
  • 在 ES7 中使用 Symbol.iterator 实现自定义迭代器

    在 ES7 中使用 Symbol.iterator 实现自定义迭代器 迭代器是 JavaScript 中非常有用的一个概念,它可以让我们以一种可控和可迭代的方式遍历一个数据集合。

    1 年前
  • Linux 高性能网络编程技巧

    Linux 作为一款强大的操作系统,其网络编程在性能方面表现非常优秀。在前端开发中,我们经常需要进行网络通信,因此了解 Linux 高性能网络编程技巧对于前端开发人员也是很有指导意义的。

    1 年前
  • Babel 中如何使用 Class Properties 和 Class Fields

    在现代 JavaScript 中,类 (Class) 是一种非常常见的编程方式。但是,JavaScript 中的 Class 功能相对于其他编程语言来说还比较青涩,缺乏一些基本的语法特性,例如:cla...

    1 年前
  • RESTful API 中的数据过滤详解

    随着 RESTful API 的广泛应用,越来越多的 Web 应用程序需要检索数据并根据用户的需要返回特定的数据。在大型系统中,数据过滤变得尤为重要,因为过滤数据可以减少返回的数据量并提高系统的响应速...

    1 年前
  • 从拍平数组到递归对象:解析 ES11 新增的 array.flat、arr.filter 和 Object.fromEntries

    在前端开发中,经常会遇到对数组和对象的操作,特别是在对数据进行处理和展示时,对数据的操作是不可或缺的。ES11 新增了一些数组和对象的新方法,本文将详细介绍其中的 array.flat、arr.fil...

    1 年前
  • 在 Node.js 项目中如何集成 ESLint

    在 Node.js 项目中如何集成 ESLint 随着 JavaScript 代码量的不断增长和团队协作的加强,代码风格的一致性逐渐变得非常重要。ESLint 是一个功能强大的 JavaScript ...

    1 年前
  • 无障碍设备开发与智能家居应用的结合

    随着科技的不断发展,智能家居应用越来越普及,它能给人们带来很多便利,例如:自动化控制、节能减排等等。但是有一个问题必须要面对:智能家居应用是否也能让使用一些特殊设备、例如视力、听力等障碍的人士得...

    1 年前
  • Chai 如何断言两个浮点数是否接近

    Chai 如何断言两个浮点数是否接近 在前端编程中,我们经常需要比较浮点数的值。然而,由于浮点数的精度问题,可能会导致两个看似相等的浮点数在比较时出现误差。为了应对这个问题,Chai 提供了一个接近断...

    1 年前
  • ECMAScript 2019 (ES10): 利用 closure 可尝试模拟私有属性实现

    在 JavaScript 中,我们经常需要在对象中定义私有属性。而如果使用传统的方法,我们通常需要使用下划线前缀命名属性来表示它们是私有的。但在 ECMAScript 2019 (ES10) 中,我们...

    1 年前
  • Express.js 中使用 body-parser 中间件解析 POST 请求参数

    介绍 在 Node.js 和 Express.js 中,处理 HTTP 请求是非常常见的任务。虽然 GET 请求可以将参数放在 URL 中,但 POST 请求通常需要将参数放在请求正文中。

    1 年前
  • 盘点 Web Components 的优点和缺点

    随着前端技术的不断进步和发展,我们也不断的迎来新的开发理念和技术概念。Web Components 是一个很好的例子,它可以被看作是一种新型的前端开发技术。这里我们将详细讨论 Web Componen...

    1 年前
  • 基于 JWT 的认证和授权在 Next.js 中的应用实践

    基于 JWT 的认证和授权在 Next.js 中的应用实践 前言 基于 JWT 的认证和授权在现在的前后端开发中已成为一种常见的方式。Next.js 是一个非常流行的 React 框架,它提供了服务器...

    1 年前
  • 用 PM2 部署 Node.js 项目

    在 Node.js 项目中,部署是一个必须要考虑的问题。因为 Node.js 项目的本质是单线程、异步 IO,能承受的请求是有限的,而且 Node.js 代码在处理请求时也需要加载一些资源,比如代码、...

    1 年前
  • Angular 中如何实现下拉框

    下拉框(dropdown)是前端开发中常用的组件之一,它通常用于选择某个选项或展示下拉菜单。Angular 是一个流行的前端框架,在 Angular 中实现下拉框的过程也比较简单。

    1 年前

相关推荐

    暂无文章