服务器推送数据你还在用 WebSocket么?

news2025/2/24 14:42:35

当涉及到推送数据时,人们首先会想到 WebSocket。

的确,WebSocket 允许双向通信,可以自然地用于服务器到浏览器的消息推送。

然而,如果只需要单向的消息推送,HTTP 通过服务器发送的事件也有这种功能。

WebSocket 的通信过程如下:

首先,通过 HTTP 切换协议。服务器返回 101 状态码后,协议切换成功。

然后,开始以 WebSocket 格式的数据通信,任意一方都可以随时向另一方推送消息。

至于 HTTP 中的服务器发送的事件:

服务器返回的 Content-Typetext/event-stream,这是一种可以多次返回内容的流。

服务器发送的事件通过这种类型的消息随时推送数据。

你可能是第一次听说 SSE,但你已经使用过基于它的应用程序。

例如,你使用的 CI/CD 平台会实时打印日志。

那么它如何实时传输构建日志呢?

它需要分次传输,SSE 通常用于以这种方式推送数据。

另一个例子是 ChatGPT。它在回答问题时不会一次给你所有答案,而是逐步分块加载。

这也是基于 SSE 的。

现在我们已经知道 SSE 是什么以及它的应用,让我们自己实现它。

创建一个 Nest 项目。

npx nest new sse-test

运行它:

访问 http://localhost:3000 会显示“Hello World”,表示服务器运行成功。

然后在 AppController 中添加一个流接口。

这里没有用 @Get@Post 等装饰器进行标识,而是 @Sse 装饰器表示这是一个事件流类型的接口。

@Sse('stream')
stream() {
    return new Observable((observer) => {
      observer.next({ data: { msg: 'aaa'} });

      setTimeout(() => {
        observer.next({ data: { msg: 'bbb'} });
      }, 2000);

      setTimeout(() => {
        observer.next({ data: { msg: 'ccc'} });
      }, 5000);
    });
}

返回的是 Observable 对象,然后在内部使用 observer.next 返回消息。可以返回任何 JSON 数据。我们首先返回 aaa,2 秒后返回 bbb,5 秒后返回 ccc。然后创建一个前端页面:创建一个 React 项目。

npx create-react-app --template=typescript sse-test-frontend

App.tsx 中编写以下代码:

import { useEffect } from 'react';

function App() {

  useEffect(() => {
    const eventSource = new EventSource('http://localhost:3000/stream');
    eventSource.onmessage = ({ data }) => {
      console.log('New message', JSON.parse(data));
    };
  }, []);

  return (
    <div>hello</div>
  );
}

export default App;

这个 EventSource 是浏览器的原生 API,用于获取 SSE 接口的响应。它会将每个消息传入回调函数 onmessage 中。

我们在 Nest 服务中启用跨域支持。

然后删除 react 项目中的 index.tsx 文件中的这几行代码,因为它们会导致额外的渲染:

执行 npm run start

因为 3000 端口被占用,它将在 3001 上运行:

访问浏览器:

看到响应了吗?

这就是服务器发送的事件。

devtools 中,你可以看到响应的 Content-Typetext/event-stream

然后在 EventStream 中,你可以看到接收到的每条消息。

通过这种方式,服务器可以随时向网页推送消息。

它的兼容性如何?

你可以在 MDN 上看到。

除了 IE 和 Edge 外,与其他浏览器没有兼容问题。

一般来说,安全使用。

它可以在哪里使用?

服务器发送的事件 特别适合只需要服务器端推送的场景。

例如日志的实时推送。

让我们测试一下:

“tail -f”命令允许你实时查看文件的最新内容。

我们使用 child_process 模块的 exec 函数来执行这个命令,然后监听它的 stdout 输出。

const { exec } = require("child_process");

const childProcess = exec('tail -f ./log');

childProcess.stdout.on('data', (msg) => {
    console.log(msg);
});

使用 node 执行它。

然后添加一个 SSE 接口。

@Sse('stream2')
stream2() {
const childProcess = exec('tail -f ./log');

return new Observable((observer) => {
  childProcess.stdout.on('data', (msg) => {
    observer.next({ data: { msg: msg.toString() }});
  })  
});

检测到新数据后,返回到浏览器。

浏览器连接到这个新接口:

测试如下:

可以看到浏览器已经接收到实时日志。

许多构建日志都是通过 SSE 实时推送的。

日志和类似的东西只是文本,但是如果是二进制数据呢?

在 Node.js 中,二进制数据存储在 Buffer 中。

const { readFileSync } = require("fs");

const buffer = readFileSync('./package.json');

console.log(buffer); 

Buffer 有一个 toJSON 方法:

这可以通过 SSE 接口返回吗?

试一下:

@Sse('stream3')  
stream3() {
    return new Observable((observer) => {
        const json = readFileSync('./package.json').toJSON();
        observer.next({ data: { msg: json }});
    });
}

的确可以。

换句话说,基于 SSE,除了可以推送文本,还可以推送任何二进制数据。

概括

可以使用 WebSocket 或 HTTP 的服务器发送事件(SSE)从服务器推送实时数据。

通过在 HTTP 响应中返回一个 Content-Type 为 text/event-stream 的头,可以通过流多次发送消息。

传输的内容是 JSON 格式,可以用来传输文本或二进制内容。

我们使用 Nest 实现了 SSE 接口。方法使用 @Sse 装饰器进行注释,它返回一个 Observable 对象。可以使用 observer.next 随时返回数据。

在前端,使用 EventSource 的 onmessage 来接收消息。

这个 API 在除 IE 和 Edge 外的其他浏览器有很好的兼容性,可以安全使用。

它有各种应用,如内部消息传递、构建日志的实时显示和 chatgpt 的消息响应。

当遇到需要消息推送的场景时,考虑使用服务器发送的事件而不是 WebSocket。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1391552.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Shell脚本同时调用#!/bin/bash和#!/usr/bin/expect

如果你想在一个脚本中同时使用bash和expect&#xff0c;你可以将expect部分嵌入到bash脚本中。以下是一个示例&#xff1a; #!/bin/bash# 设置MySQL服务器地址、端口、用户名和密码 MYSQL_HOST"localhost" MYSQL_PORT"3306" MYSQL_USER"your_usernam…

Shiro漏洞

VULHUB部署环境 下载vulhub https://github.com/vulhub/vulhub/archive/master.zip?spma2c6h.12873639.article-detail.7.76036a98Plc8q5&filemaster.zip 进入漏洞文件夹直接部署 界面 漏洞 如果勾选记住账号&#xff0c;请求包会附带remember-me字段&#xff0c;服务…

转行做鸿蒙开发首先需要学习哪些?

随着越来越多的企业和团队开始布局鸿蒙生态&#xff0c;鸿蒙开发人才的需求也呈现出井喷式的增长。对于开发者而言&#xff0c;掌握鸿蒙开发技能不仅意味着能够抓住这个千载难逢的机遇&#xff0c;更意味着能够在未来的科技竞争中占据先机。 在这个变革的时代&#xff0c;鸿蒙开…

数据结构与算法:归并排序

数据结构与算法&#xff1a;归并排序 归并思想递归法非递归 归并思想 在讲解归并排序前&#xff0c;我们先看到一个问题&#xff1a; 对于这样两个有序的数组&#xff0c;如何将它们合并为一个有序的数组&#xff1f; 在此我们处理这个问题的思路就是&#xff1a;开辟一个新的…

码云星辰:未来运维的技术交响曲

&#x1f6a9;本文介绍 ​ 随着信息技术的迅猛发展&#xff0c;运维领域正经历着翻天覆地的变革。未来的运维工程师将需要拥有更广泛、更深入的技能&#xff0c;以适应日益复杂和多变的系统环境。本文将深入探讨运维未来的行业发展趋势&#xff0c;并详细分析需要掌握的关键技…

java web万能模板(附带防微博源码)

文章目录 java EE 项目万能模板套用创建一个java EE项目1.点击java ee2.点击finish3.一个Java ee项目创建完毕4.点击运行5.运行结果 万能模板连接数据库1.在pom.xml文件导入数据库连接所需要的依赖2.进行导入3. 导入以后刷新Maven4.找到 resources 文件。5.在resources的文件路…

【论文阅读笔记】4篇Disentangled representation learning用于图像分割的论文

4篇应用解耦表示学习的文章&#xff0c;这里只关注如何解耦&#xff0c;更多细节不关注&#xff0c;简单记录一下。 1.Robust Multimodal Brain Tumor Segmentation via Feature Disentanglement and Gated Fusion Chen C, Dou Q, Jin Y, et al. Robust multimodal brain tum…

trucksim与simulink联合仿真基于pid控制算法实现车道保持

一、pid算法原理不做过多解释自行百度&#xff0c;这里采用的是位置式pid。 效果视频&#xff1a;https://www.bilibili.com/video/BV1CN4y1p7gb/?vd_sourcea1425ad8eaf3586e891a6d0040eb89cc 二、trucksim界面操作截图 三、simulink模型截图 采用的P &#xff1b; I和…

NG+WAF实现应用安全访问

一、基本概念 什么是waf&#xff1f; Web应用防火墙&#xff08;waf&#xff09;是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品&#xff0c;WAF是一种工作在应用层的、通过特定的安全策略来专门为Web应用提供安全防护的产品。 什么是ngx_lua_…

SparkSQL——DataFrame

DataFrame Dataframe 是什么 DataFrame 是 SparkSQL中一个表示关系型数据库中 表的函数式抽象, 其作用是让 Spark处理大规模结构化数据的时候更加容易. 一般 DataFrame可以处理结构化的数据, 或者是半结构化的数据, 因为这两类数据中都可以获取到 Schema信息. 也就是说 DataFra…

2018年认证杯SPSSPRO杯数学建模B题(第一阶段)动态模糊图像全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 B题 动态模糊图像 原题再现&#xff1a; 人眼由于存在视觉暂留效应&#xff0c;所以看运动的物体时&#xff0c;看到的每一帧画面都包含了一段时间内 (大约 1/24 秒) 的运动过程&#xff0c;所以这帧画面事实上是模糊的。对电影的截图来说&…

eNSP学习——终端直连三层网关设备进行通信

VLAN 配置 一 . 功能简介 将设备中的某些接口定义为一个单独的区域&#xff0c;将指定接口加入到指定 VLAN 中之后&#xff0c;接口就可以转发 指定 VLAN 报文。从而实现 VLAN 内的主机可以直接通信&#xff0c;而 VLAN 间的主机不能直接互通&#xff0c;将广播报文 …

前端安全相关

请求后端接口必须带上sign 以上主要是解决&#xff1a;除了数据泄露外&#xff0c;一些重要功能的接口如果没有做好保护措施也会被恶意调用造成DDoS、条件竞争等攻击效果 一些营销活动类的Web页面&#xff0c;领红包、领券、投票、抽奖等活动方式很常见。此类活动对于普通用户…

Linux miniGUI移植分析

框架介绍 常用GUI程序对比 https://www.cnblogs.com/zyly/p/17378659.html MiniGUI分为底层的GAL&#xff08;图形抽象层&#xff09;和IAL&#xff08;输入抽象层&#xff09;&#xff0c;向上为基于标准POSIX接口中pthread库的Mini-Thread架构和基于Server/Client的Mini-L…

WebGL中开发AR应用

WebGL在本质上是用于在浏览器中进行3D和2D图形渲染的技术&#xff0c;而增强现实&#xff08;AR&#xff09;通常需要与现实世界的环境进行交互。要在WebGL中开发AR应用&#xff0c;您可以采取以下步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专…

固定拍摄点位下的NeRF技术应用(算法探讨)

NeRF&#xff08;神经辐射场&#xff09;技术可以用于物体定位。NeRF 是一种深度学习方法&#xff0c;它通过对场景的大量照片进行训练来创建三维场景的高度逼真的渲染。这项技术能够从多个角度捕捉场景的细节&#xff0c;并通过神经网络理解场景的三维结构。 使用 NeRF 进行物…

容器部署的nextcloud配置onlyoffice时开启密钥

容器部署的nextcloud配置onlyoffice时开启密钥 配置 进入onlyoffice容器 docker exec -it 容器id bash编辑配置vi /etc/onlyoffice/documentserver/local.json enable设置为true&#xff0c;并配置secret 重启容器&#xff0c;并将配置的密钥填入nextcloud密钥页面 docker r…

协方差矩阵自适应调整的进化策略(CMA-ES)

关于CMA-ES&#xff0c;其中 CMA 为协方差矩阵自适应(Covariance Matrix Adaptation)&#xff0c;而进化策略&#xff08;Evolution strategies, ES&#xff09;是一种无梯度随机优化算法。CMA-ES 是一种随机或随机化方法&#xff0c;用于非线性、非凸函数的实参数&#xff08;…

【每日小bug】mybatis plus id注解错误导致的问题

插入数据 id不为自增 指定了主键&#xff0c;没有指定自增。会导致出现 修改如上 报错 Data truncation: Out of range value for column ‘id’ at row 1 数据库是bigint&#xff0c;java中是Integer。 修改如上

现代工程科技杂志现代工程科技杂志社现代工程科技编辑部2023年第21期目录

能源科技 配网故障停电原因及改进对策研究 上官安琪 110kV变电站电气自动化技术及应用策略 陈祥 变电运维误操作事故预控措施分析 高翔;韦婉 智能变电站变电运维安全与设备维护探究 温亮亮;覃万全 110kV变电站电气设计及其防雷保护案例研析 谢旭平 变电运维…