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

在这里插入图片描述

当涉及到推送数据时,人们首先会想到 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.hqwc.cn/news/411370.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

首届PolarDB开发者大会在京举办,阿里云李飞飞:云数据库加速迈向智能化

1月17日&#xff0c;阿里云PolarDB开发者大会在京举办&#xff0c;中国首款自研云原生数据库PolarDB发布“三层分离”新版本&#xff0c;基于智能决策实现查询性能10倍提升、节省50%成本。此外&#xff0c;阿里云全新推出数据库场景体验馆、训练营等系列新举措&#xff0c;广大…

test-02-test case generate 测试用例生成 EvoSuite 介绍

拓展阅读 junit5 系列 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) Junit performance rely on junit5 and jdk8.(java 性能测试框架。性能测试。压测。测试报告生成。) 拓展阅读 自动生成测试用例 什么…

网络部署实战具体学习内容总结

网络部署实战具体学习内容总结 &#x1f4bb;网络部署实战课程通常旨在教授学生如何规划、配置、维护和优化计算机网络。这些课程涵盖了广泛的主题&#xff0c;以确保学生具备网络部署和管理所需的技能。 网络部署实战课程具体学习内容&#x1f447; 1️⃣网络架构设计及网络原…

AMRT3D使用指南:基于快速搭建3D场景的高频问答

在3D领域有所涉猎的朋友&#xff0c;相信对于3D引擎都不会陌生。自从数字孪生、3D应用提上战略规划后&#xff0c;开发者都希望尽快完成高质量的3D可视化开发实战&#xff0c;企业都希望高效集成三维能力&#xff0c;结合业务快速落地&#xff0c;最直接的方式就是通过3D引擎来…

DP读书:《openEuler操作系统》(七)FSCK与VFS虚拟文件系统

10min速通FSCK、原子操作与VFS 文件系统检查器1.检查inode表1) 遍历所有inode2) 修复多次引用数据块 2.检查目录结构3.检查目录的连接1) 检查根目录确保存在2) 遍历所有目录的inode,有问题的连接到/lostfound 4.检查引用次数5.检查位图一致性 日志1.主要的数据结构1) 原子操作描…

数据结构之串

数据结构之串 1、串的定义及基本运算2、串的存储结构3、串的模式匹配 数据结构是程序设计的重要基础&#xff0c;它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发&#xff0c;分析和研究计算机加工的数据的特性&#xff0c;以便…

git-生成证书、公钥、私钥、error setting certificate verify locations解决方法

解决方法 方法1-配置证书、公钥、私钥打开Git Bash设置名称和邮箱执行&#xff0c;~/.ssh执行&#xff0c;ssh-keygen -t rsa -C "这是你的邮箱"&#xff0c;如图&#xff1a;进入文件夹可以看到用记事本之类的软件打开id_rsa.pub文件&#xff0c;并且复制全部内容。…

P9842 [ICPC2021 Nanjing R] Klee in Solitary Confinement 题解(SPJ!!!)

[ICPC2021 Nanjing R] Klee in Solitary Confinement 题面翻译 给定 n , k n,k n,k 和一个长为 n n n 的序列&#xff0c;你可以选择对区间 [ l , r ] [l, r] [l,r] 的数整体加上 k k k&#xff0c;也可以不加。最大化众数出现次数并输出。 题目描述 Since the travele…

制造领域 智能制造典型场景参考指引

智能制造场景是智能工厂的核心组成部分&#xff0c;是指面向制造过程各个环节&#xff0c;通过新一代信息技术、先进制造技术的深度融合&#xff0c;部署高档数控机床与工业机器人、增材制造装备、智能传感与控制装备、智能检测与装配装备、智能物流与仓储装备、行业成套装备等…

Windows 下 PYQT开发环境的搭建:

(1)环境搭建&#xff1a; PYQT 安装包&#xff1a; Anaconda&#xff1a; Anaconda3-2023.09-0-Windows-x86_64 pycharm&#xff1a; pycharm 2019.3 下载包&#xff1a; Anaconda:下载成功 |蟒蛇 (anaconda.com) pycharm: pycharm安装包_pycharm用copilotchat资源-CSD…

利用 ChatGPT 高效搜索:举一反三的思考方式,高效查找解决方案

文章目录 基础思路举一反三Go 语言 Web 框架延伸思考思考结论 本文只是我的一些尝试&#xff0c;基于 ChatGPT 实现系统化快速搜索某编程语言的特定领域相关包或者基于其他语言类推荐落地方案的尝试。 这篇文章中描述的方式不一定是好方式&#xff0c;但应该会有一定的启示作用…

【Go学习】macOS+IDEA运行golang项目,报command-line-arguments,undefined

写在前面的话&#xff1a;idea如何配置golang&#xff0c;自行百度 问题1&#xff1a;通过idea的terminal执行go test报错 ✘ xxxxxmacdeMacBook-Pro-3  /Volumes/mac/.../LearnGoWithTests/hello  go test go: go.mod file not found in current directory or any parent …