Nest.js 实战 (十三):实现 SSE 服务端主动向客户端推送消息

简介: 这篇文章介绍了在Nest.js应用中使用Server-Sent Events (SSE)的技术。文章首先讨论了在特定业务场景下,为何选择SSE而不是WebSocket作为实时通信系统的实现方式。接着解释了SSE的概念,并展示了如何在Nest.js中实现SSE。文章包含客户端实现的代码示例,并以一个效果演示结束,总结SSE在Nest.js中的应用。

前言

假如系统又一个这样的业务场景:已登录的用户发起流程或者发布消息之后,需要弹窗通知其他已登录的用户,我们应该如何实现?

在设计实时通信场景时,我们面临的主要挑战是如何有效地通知所有已登录的用户有关新流程的启动或新消息的发布。为了实现这一目标,我们需要一个既能高效推送信息又能保证低延迟的技术方案。在评估了 WebSocketServer-Sent Events (SSE) 两种技术之后,我们选择了 SSE) 作为实时通信系统的实现方式。

尽管 WebSocket 提供了全双工通信的能力,使得客户端和服务器可以在任何时候互相发送数据,但在我们的应用场景中,主要的需求是由服务器向客户端发送更新通知,而客户端不需要向服务器发送相关的数据。因此,我们不需要 WebSocket 提供的全双工特性。

本篇文章将详细介绍如何在 Nest.js 应用中使用 Server-Sent Events (SSE)

什么是 Server-Sent Events?

Server-Sent Events (SSE) 是一种让服务器能够实时地向客户端发送数据的技术。传统的 Web 应用程序都是基于客户端发起请求,服务器响应这一模式的。然而,在某些应用场景下,比如股票行情、聊天应用或实时更新的数据展示等,需要服务器主动向客户端推送信息。

SSE 提供了一个简单的单向事件流,使得服务器能够在客户端请求保持打开的状态下推送更新。这样做的好处是减少了轮询请求所带来的网络开销,并且能够让客户端即时接收到新的数据更新。

yf6xtvpxtimwrwartjzsdi1czai0aoyt.jpg

SSE 优点

  1. 单向通信SSE 默认只支持从服务器到客户端的单向数据传输。
  2. 格式简单SSE 的消息格式非常简单,易于理解和解析。
  3. 持久连接:客户端与服务器之间的连接保持打开状态,直到一方关闭为止。
  4. 断线重连:当连接中断后,客户端可以尝试重新建立连接以继续接收事件。

@Sse 装饰器

在需要消息推送的 Controller 方法中使用 @Sse 装饰器

import {
   
    Sse } from '@nestjs/common';

@Sse('sse/event')
sse(): Observable<MessageEvent> {
   
   
  return new Observable<any>((observer) => {
   
   
    // 监听事件
    this.eventEmitter.on(EVENTBUS_TYPE.MESSAGE_CREATE, (data: Message) => {
   
   
      observer.next({
   
    data });
    });
  });
}

因为我这里是别的方法执行成功后,才需要向客户端执行消息推送,所以这里使用了 Event Emitter

客户端实现

onMounted(() => {
   
   
  const eventSource = new EventSource(
    "http://localhost:3000/sse/event",
   ;
  eventSource.onmessage = ({
   
    data }) => {
   
   
    console.log("New message", JSON.parse(data));
  };
});

原生 EventSource 是不支持设置请求等信息的,详情可以查看MDN 文档

如果你的接口设置了访问权限,比如需要请求头携带 token 才能访问,那么你需要使用别的连接方式,比如:event-source-polyfill

EventSourcePolyfill

event-source-polyfillEventSource 封装的一个方法,可以配置请求头

1、 安装依赖

pnpm add event-source-polyfill

2、 示例代码

import {
   
    EventSourcePolyfill } from 'event-source-polyfill';

// 创建 EventSource 实例
const eventSource = new EventSourcePolyfill(`${
     
     baseURL}/sse/event`, {
   
   
  headers: {
   
   
    Authorization: `Bearer ${
     
     authStore.token}`,
  },
  heartbeatTimeout: 60 * 60 * 1000, // 这是自定义配置请求超时时间  默认是45000ms
});

// 接收消息
eventSource.onmessage = ({
   
    data }:MessageEvent) => {
   
   
  console.log("New message", JSON.parse(data));
};

onBeforeUnmount(() => {
   
   
  // 组件卸载前关闭连接
  eventSource.close();
});

效果演示

同时登陆两个用户,其中一个发布消息时,服务器会向所有客户端推送消息:
wuvs5yrlbk3hf49raedkamw7m65rq1j3.gif

浏览器查看接口接收消息:
aasfywqy40af63e2721uh62rvt0px3vq.png

总结

关注我,我们一起领略 Nest.js 的魅力

GithubVue3-Admin

相关文章
|
15天前
|
JavaScript
Nest.js 实战 (十一):配置热重载 HMR 给服务提提速
这篇文章介绍了Nest.js服务在应用程序引导过程中,TypeScript编译对效率的影响,以及如何通过使用webpackHMR来降低应用实例化的时间。文章包含具体教程,指导读者如何在项目中安装依赖包,并在根目录下新增webpack配置文件webpack-hmr.config.js来调整HMR相关的配置。最后,文章总结了如何通过自定义webpack配置来更好地控制HMR行为。
|
18天前
|
SQL 运维 监控
Nest.js 实战 (十):使用 winston 打印和收集日志记录
这篇文章介绍了在Nest服务中如何使用Winston记录日志。文章首先强调了日志记录在后台服务中的重要性,接着提到Nest默认的内部日志记录器,并指出可以通过@nestjs/common包中的Logger类来全面控制日志系统的行为。文章还提到,为了在生产环境中实现更高级的日志功能,可以使用如Winston之类的Node.js日志包。接下来,文章介绍了如何在Nest服务中使用Winston记录日志,包括安装相关依赖、创建winston配置文件以及实现简单的日志记录示例。最后,文章指出更高级的自定义日志功能需要读者自己去探索。
Nest.js 实战 (十):使用 winston 打印和收集日志记录
|
8天前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.
|
22天前
|
JavaScript 数据安全/隐私保护 Python
网易云音乐搜索接口JS逆向: Params、encSecKey加密和AES实战
网易云音乐搜索接口JS逆向: Params、encSecKey加密和AES实战
21 4
|
19天前
|
前端开发 JavaScript 开发者
前端JS按钮点击事件、跳出弹窗、遮罩的实战示例
本文提供了一个前端JS按钮点击事件、弹出式窗口和遮罩层的实战示例,包括HTML、CSS和JavaScript的具体实现代码,以及功能解析,演示了如何实现按钮点击后触发弹窗显示和遮罩层,并在2秒后自动关闭或点击遮罩层关闭弹窗的效果。
前端JS按钮点击事件、跳出弹窗、遮罩的实战示例
|
22天前
|
JavaScript 前端开发 安全
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
26 2
|
27天前
|
JSON JavaScript 前端开发
JS的无限可能: 前端 精妙DOM技巧至Node.js的服务端
JS的无限可能: 前端 精妙DOM技巧至Node.js的服务端
|
1月前
|
JavaScript 前端开发
JavaScript基础&实战 JS中正则表达式的使用
这篇文章介绍了JavaScript中正则表达式的使用,包括正则表达式的创建、匹配模式、字符串匹配、拆分、搜索、匹配和替换等方法,并通过示例代码展示了如何应用这些技术。
JavaScript基础&实战 JS中正则表达式的使用
|
1月前
|
JavaScript 前端开发
JavaScript基础&实战(5)js中的数组、forEach遍历、Date对象、Math、String对象
这篇文章介绍了JavaScript中的数组、Date对象、Math对象以及包装类(String、Number、Boolean),并详细讲解了数组的创建、方法(如forEach、push、pop、unshift、slice、splice)和遍历操作,以及工厂方法创建对象和原型对象的概念。
JavaScript基础&实战(5)js中的数组、forEach遍历、Date对象、Math、String对象
|
17天前
|
前端开发 Java UED
JSF 面向组件开发究竟藏着何种奥秘?带你探寻可复用 UI 组件设计的神秘之路
【8月更文挑战第31天】在现代软件开发中,高效与可维护性至关重要。JavaServer Faces(JSF)框架通过其面向组件的开发模式,提供了构建复杂用户界面的强大工具,特别适用于设计可复用的 UI 组件。通过合理设计组件的功能与外观,可以显著提高开发效率并降低维护成本。本文以一个具体的 `MessageComponent` 示例展示了如何创建可复用的 JSF 组件,并介绍了如何在 JSF 页面中使用这些组件。结合其他技术如 PrimeFaces 和 Bootstrap,可以进一步丰富组件库,提升用户体验。
27 0