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

相关文章
|
4月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
247 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
10天前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
2月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
87 1
|
7月前
|
前端开发 JavaScript Java
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
333 13
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
|
6月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
监控 安全 中间件
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
这篇文章介绍了什么是Next.js中的中间件以及其应用场景。中间件可以用于处理每个传入请求,比如实现日志记录、身份验证、重定向、CORS配置等功能。文章还提供了一个身份验证中间件的示例代码,以及如何使用限流中间件来限制同一IP地址的请求次数。中间件相当于一个构建模块,能够简化HTTP请求的预处理和后处理,提高代码的可维护性,有助于创建快速、安全和用户友好的Web体验。
202 0
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
|
中间件 API
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
这篇文章介绍了作者在使用Nextjs15进行项目开发时遇到的部署问题。在部署过程中,作者遇到了打包构建时的一系列报错,报错内容涉及动态代码评估在Edge运行时不被允许等问题。经过一天的尝试和调整,作者最终删除了lodash-es库,并将radash的部分源码复制到本地,解决了打包报错的问题。文章最后提供了项目的线上预览地址,并欢迎读者留言讨论更好的解决方案。
227 0
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
295 0
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
|
JavaScript 前端开发 API
Next.js 实战 (六):如何实现文件本地上传
这篇文章介绍了在Next.js中如何实现文件上传到本地的方法。文章首先提到Next.js官方文档中没有提供文件上传的实例代码,因此开发者需要自行实现,通常有两种思路:使用Node.js原生上传或使用第三方插件如multer。接着,文章选择了使用Node.js原生上传的方式来讲解实现过程,包括如何通过哈希值命名文件、上传到指定目录以及如何分类文件夹。然后,文章展示了具体的实现步骤,包括编写代码来处理文件上传,并给出了代码示例。最后,文章通过一个效果演示说明了如何通过postman模拟上传文件,并展示了上传后的文件夹结构。
222 0
Next.js 实战 (六):如何实现文件本地上传
|
前端开发 API 开发者
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画
这篇文章介绍了Framer Motion,一个为React设计的动画库,提供了声明式API处理动画和页面转换,适合创建响应式用户界面。文章包括首屏加载动画、路由加载Loading、路由进场和退场动画等主题,并提供了使用Framer Motion和next.js实现这些动画的示例代码。最后,文章总结了这些效果,并邀请读者探讨更好的实现方案。
288 0
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画