利用 Server-Sent Events 解决 Web 应用中的状态同步问题

前言

现代 Web 应用往往涉及到不同的浏览器端和服务端之间的状态同步问题。例如聊天应用需要在客户端和服务端之间持续传递消息状态,实时地更新聊天室或聊天联线;或者协同编辑应用需要客户端间同步文档状态,保证多个用户同时编辑文档时的一致性等等。这些应用场景如果要使用传统的异步轮询或长轮询技术来实现状态同步则会带来网络负担和性能问题,延迟也无法保证,我们需要一种更有效、实时的解决方案。

本文将介绍一种新的状态同步技术:Server-Sent Events(即服务端推送事件,下文简称 SSE),它提供了低延迟的、轻量级的、可靠的对浏览器的事件推送机制,并且适用于多种状态同步场景,可用于增强许多 Web 应用功能。

SSE 概述

SSE 是一种基于 HTTP 技术的服务端推送事件技术。它允许服务器向客户端推送新的数据,而不需要浏览器发起任何请求。SSE 的实现基于一个持续的 HTTP 连接,这个连接指向服务器端的一个特殊的 URL,称之为事件源(EventSource)。事件源通过一个 SSI(Server-Sent Inclusions)HTML 格式页面的形式,向客户端发送数据,客户端则通过 EventSource API 来监听服务器端事件,并接收 & 处理数据。

SSE 相比于其他传统的 Web 应用实时通信技术,有很多优势:

  • 轻量级,无需下载额外的框架或库
  • 无需轮询机制,减少网络请求和服务器负载
  • 基于 HTTP 协议,通过反向代理、SSL/TLS 都能正常工作
  • 可靠性较高,具备自动重连,断线自动恢复等机制

SSE 工作原理

事件源

事件源是 SSE 技术的核心,是服务端产生事件的地方。它是一个特殊的 URI,与 Web 页面的 URL 不同。客户端通过这个 URI 并不是为了读取或者获取页面内容,而是建立了一个长连接,然后等待事件的出现。

事件源的生成过程通常像这样:

  1. 客户端向服务器发出一个普通的 HTTP GET 请求
  2. 服务器通过响应消息体或响应头的某个信息告诉客户端,这个请求是一个通道,不需要关闭
  3. 之后,客户端和服务器之间的连接不会被关闭,除非手动触发关闭请求或网络中断。

在响应头中,我们可以采用 "text/event-stream" 的特殊 MIME(Multipurpose Internet Mail Extensions)格式,告知客户端它是一个 SSE 对象。Content-Type 的值为 "text/event-stream",这是所有 SSE 服务器必须发送的响应头的一部分。

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

客户端收到响应后,就可以开始监听从该请求通道传递过来的消息了。

事件类型

事件源可以发射很多事件,每个事件都是由一个字符串的「事件类型」和数据(可选)组成的。这个事件类型会被放在响应流中的响应头字段名字为 "event:" 的字段中,而数据则是放在流数据体中。

例如,一个消息包括了一个消息类型和一些数据:

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

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

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

推送数据

在客户端与事件源上建立了 SSE 连接后,服务器可以在特定的时间,向客户端发送新的数据,时刻保证客户端能够实时得到新的数据,来实现状态同步的需求。

在推送数据时,服务器需要将发送的数据整理为 SSE 统一的格式,这个格式大致如下:

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

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

其中, 表示事件名称,可以用字符串表示, 是 JSON 格式的字符串,在客户端的 onmessage 事件中可以解析出数据, 字段是可选的表示消息的唯一标识,使客户端能够在下一次连接 SSE 前缓存消息。

客户端接收数据

在客户端,我们可以通过 JavaScript 中的 EventSource API 建立对 SSE 的连接,并且可以监听到发生的各种事件。

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

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

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

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

在这个例子中,我们指定一个名为 /event-stream 的事件源,并将其用于事件监听。我们通过监听来自事件源的三个事件处理函数,分别处理「事件到达了」、「打开了连接」和「发生了错误」事件。

SSE 示例代码

下面是一个示例,展示了一个 SSE 服务器产生事件的过程,以及客户端使用 EventSource API 处理事件流的过程:

服务端

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

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

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

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

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

客户端

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

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

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

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

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

总结

SSE 技术是一种实用、简单、可靠的状态同步技术,可以应用于许多不同的 Web 应用场景,如网页聊天、数据监控、即时通知、实时多人协同编辑等。它基于 HTTP 和浏览器端 EventSource API 构建,免去了传统的轮询和长轮询机制的复杂性和低效,有利于实现更高效、更智能的 Web 应用。

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


猜你喜欢

  • Kubernetes 项目引擎之 Service Mesh Envoy

    在微服务架构中,服务间通信是非常重要的。然而,在实现服务间通信时,需要考虑到服务发现、负载均衡、安全性、监控等多个方面。而在 Kubernetes 项目中,Service Mesh Envoy 就是一...

    1 年前
  • Express.js+MySQL 初学者入门教程

    近年来,前端开发已经成为了IT行业中最为热门的领域之一。大量的公司和个人都在将自己的产品和服务迁移至Web平台,这样以来,对于前端开发的需求也在不断增加。在前端开发中,Express.js和MySQL...

    1 年前
  • Vue.js 中的动画 - 过渡模式详解

    前言:Vue.js 是一款非常流行的前端框架之一,它能够帮助开发者构建交互式应用程序,提供了许多非常有用的功能。动画是其中一个很重要的特性,而在 Vue.js 中,动画主要就是基于过渡模式实现的。

    1 年前
  • SPA 为什么会影响 SEO?

    什么是 SPA? SPA(Single Page Application)指的是单页应用程序,是一种 Web 应用程序的设计方法,通过使用 Ajax 和 HTML5 来构建交互性更强的 Web 网站或...

    1 年前
  • ES7 中的新特性:尾调用优化

    在 JavaScript 中,尾调用是一种函数调用的形式,它出现在函数的最后一个语句,并返回函数结果。尾调用优化就是指在执行这种调用时,JavaScript 引擎会对栈进行优化,使其在调用结束后能够立...

    1 年前
  • TypeScript 中的布尔类型

    TypeScript 是一种静态类型检查的 JavaScript 超集,它提供了一些语法和语义上的扩展,使得我们可以更加轻松地编写类型安全的代码。其中之一就是 TypeScript 提供了一种布尔类型...

    1 年前
  • Next.js 应用如何处理请求头与响应头?

    随着互联网技术的不断进步,越来越多的网站和应用程序采用了前后端分离的架构,这也就意味着前端必须要有一定的后台开发知识。Next.js 是一种基于 React 的服务端渲染框架,既具备前端的开发灵活性,...

    1 年前
  • 基于 Deno 的框架设计

    简介 Deno 是一个由 Node.js 创始人 Ryan Dahl 发布的一种运行时,它支持 TypeScript 和 JavaScript。Deno 通过安全性、开箱即用的内置工具和高效性来吸引开...

    1 年前
  • 实战 GraphQL:如何快速构建 API

    在传统的 RESTful API 架构中,每一个资源都会对应一组 API 接口,而 GraphQL 则使用一个统一的入口,允许客户端指定需要返回的数据的结构和内容,而无需让服务端的 API 返回整个资...

    1 年前
  • Custom Elements 中众多陷阱解析

    随着 Web 技术的不断发展,传统的网页设计已经不能满足用户的需求,越来越多的网页应用需要更加丰富的交互体验。在此背景下,Custom Elements 已成为前端开发者必须掌握的技术之一。

    1 年前
  • 结合 Jest & Enzyme 的单元测试实战

    前端开发面临的挑战日益增加,为了确保代码的高质量和无误,测试是不可或缺的一个环节。在本文中,我们将通过结合 Jest 和 Enzyme,来实现前端类的单元测试。 Jest是什么? Jest 是一个由 ...

    1 年前
  • 如何让手机应用程序实现无障碍性

    无障碍性是指让所有人都能够轻松访问电子设备或在线服务。为了实现无障碍性,我们需要考虑到一些人群的特殊需求,比如视觉障碍者、听力障碍者和身体障碍者等,特别是对于手机应用程序而言,实现无障碍性更是至关重要...

    1 年前
  • ES6/7/8/9/10 中的对象方法讲解

    ES6/7/8/9/10 中的对象方法讲解 JavaScript 对象是一种非常重要的数据类型,位于程序的核心位置。在 ES6 之前,处理对象的方法往往是有限的。但是,自 ES6 开始,JavaScr...

    1 年前
  • Docker 生产环境常用基础镜像

    Docker 是一个基于容器化技术的开源应用程序创建、部署和运行平台。它可以轻松地将应用程序的运行环境打包成容器,使其可以在任何支持 Docker 的平台上运行。为了在生产环境下使用 Docker,我...

    1 年前
  • ES12 中的函数柯里化实践

    在现代前端开发中,为了创建高效且易于维护的代码,函数柯里化已经成为了一种常见的实践。ES12 中,JavaScript 引入了一些新的语言特性,这些特性使得函数柯里化的实践更加容易。

    1 年前
  • Tailwind 框架如何实现搜索框组件

    简介 Tailwind 是一种 CSS 框架,可以提供大量的样式组件来帮助前端开发人员快速构建应用程序。其中一个最常用的元素是搜索框组件,因为它是现在几乎所有应用程序中的必需元素之一。

    1 年前
  • Serverless 如何处理跨地区流量?

    Serverless 架构是一种比较新颖的云计算架构,它允许我们在不需要管理服务器的情况下构建和运行应用。相比于传统的服务器架构,Serverless 架构可以让我们更快速、更便捷地开发和部署应用程序...

    1 年前
  • Angular 引入第三方库的三种方法

    Angular 引入第三方库的三种方法 Angular 是一种流行的前端框架,无疑是许多人喜欢的选择。然而,在开发过程中,很多时候需要使用到一些第三方库来辅助开发工作,比如常见的 jQuery 和 l...

    1 年前
  • SASS 中的继承和重载混合方法的应用

    在前端开发中,CSS 是不可避免的一部分。然而,随着项目的规模和复杂度不断增加,CSS 的管理和维护变得越来越困难。SASS 就应运而生,它是一种 CSS 预编译器,可以提供更高级的样式语言和更好的代...

    1 年前
  • 使用 Web Components 实现复杂表格组件

    什么是 Web Components Web Components 是一组技术和 API,用于创建可重用的组件和封装功能。它们是由 HTML、CSS 和 JavaScript 组成的自定义元素,可以在...

    1 年前

相关推荐

    暂无文章