EventSource

什么是EventSource

EventSource 是一个用于服务器推送事件(Server-Sent Events, SSE)的接口,它允许服务器推送实时更新到浏览器。与 WebSocket 不同,SSE 是单向的(服务器到客户端),适用于更新频率不高的实时通知、消息推送等场景。下面是关于 EventSource 的详细介绍,包括使用示例和注意事项。

基本概念

  • 服务器推送事件(SSE):服务器向客户端推送实时更新,而不需要客户端发起请求。
  • EventSource 接口:浏览器端用于接收服务器推送事件的 API。

创建 EventSource 实例

要创建一个 EventSource 实例,需要传入一个 URL,这个 URL 指向服务器端的事件流端点:

const eventSource = new EventSource('https://example.com/events');

监听事件

EventSource 可以监听三种类型的事件:messageopenerror

  • message 事件:当服务器发送一个消息时触发。
  • open 事件:当连接被打开时触发。
  • error 事件:当发生错误时触发。
eventSource.onmessage = function(event) {console.log('Message:', event.data);
};eventSource.onopen = function() {console.log('Connection opened.');
};eventSource.onerror = function(event) {if (event.readyState === EventSource.CLOSED) {console.log('Connection closed.');} else {console.log('Error:', event);}
};

自定义事件

除了默认的 message 事件,你还可以监听自定义事件。服务器可以通过 event 字段来定义事件类型,客户端使用 addEventListener 来监听。

服务器发送(示例):

event: customEvent
data: This is a custom event

客户端监听:

eventSource.addEventListener('customEvent', function(event) {console.log('Custom Event:', event.data);
});

服务器端设置

服务器端需要设置适当的响应头来支持 SSE:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

并按照指定的格式发送数据:

data: This is a message\n\n

例如,使用 Node.js 和 Express 的实现:

const express = require('express');
const app = express();app.get('/events', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');res.setHeader('Cache-Control', 'no-cache');res.setHeader('Connection', 'keep-alive');setInterval(() => {res.write(`data: ${JSON.stringify({ message: 'Hello, World!' })}\n\n`);}, 1000);
});app.listen(3000, () => {console.log('Server listening on port 3000');
});

关闭连接

当不再需要接收事件时,可以关闭 EventSource 连接:

eventSource.close();
console.log('Connection closed.');

完整示例

以下是一个完整的前端和后端示例,展示了如何使用 EventSource 和 SSE。

前端(HTML + JavaScript):

<!DOCTYPE html>
<html>
<head><title>EventSource Example</title>
</head>
<body><h1>Server-Sent Events Example</h1><div id="messages"></div><script>const eventSource = new EventSource('http://localhost:3000/events');eventSource.onmessage = function(event) {const messageElement = document.createElement('div');messageElement.textContent = 'Message: ' + event```htmlmessageElement.textContent = 'Message: ' + event.data;document.getElementById('messages').appendChild(messageElement);};eventSource.onopen = function() {console.log('Connection opened.');};eventSource.onerror = function(event) {if (event.readyState === EventSource.CLOSED) {console.log('Connection closed.');} else {console.log('Error:', event);}};// Example of listening to a custom eventeventSource.addEventListener('customEvent', function(event) {const customEventElement = document.createElement('div');customEventElement.textContent = 'Custom Event: ' + event.data;document.getElementById('messages').appendChild(customEventElement);});// Close the EventSource after 10 seconds for demonstration purposessetTimeout(() => {eventSource.close();console.log('Connection closed.');}, 10000);</script>
</body>
</html>

后端(Node.js + Express):

const express = require('express');
const app = express();app.get('/events', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');res.setHeader('Cache-Control', 'no-cache');res.setHeader('Connection', 'keep-alive');// Send a simple message every secondconst intervalId = setInterval(() => {res.write(`data: ${JSON.stringify({ message: 'Hello, World!' })}\n\n`);}, 1000);// Send a custom event every 5 secondsconst customEventIntervalId = setInterval(() => {res.write(`event: customEvent\ndata: This is a custom event\n\n`);}, 5000);// Clear intervals when client closes connectionreq.on('close', () => {clearInterval(intervalId);clearInterval(customEventIntervalId);});
});app.listen(3000, () => {console.log('Server listening on port 3000');
});

详细解释

  1. 前端代码解释:

    • EventSource 实例const eventSource = new EventSource('http://localhost:3000/events'); 创建一个新的 EventSource 实例,连接到服务器的 /events 端点。
    • 事件监听
      • onmessage 处理默认的 message 事件,显示从服务器接收到的消息。
      • onopen 处理连接打开事件,输出连接已打开的信息。
      • onerror 处理错误事件,输出错误信息或连接关闭信息。
      • addEventListener('customEvent', ...) 处理自定义事件 customEvent,显示从服务器接收到的自定义事件数据。
    • 关闭连接:使用 setTimeout 在 10 秒后关闭 EventSource 连接。
  2. 后端代码解释:

    • Express 服务器:创建一个简单的 Express 服务器,监听 /events 路由。
    • 设置响应头:确保设置 Content-Type, Cache-Control, 和 Connection 头以支持 SSE。
    • 发送数据
      • 使用 setInterval 每秒发送一个消息。
      • 使用另一个 setInterval 每 5 秒发送一个自定义事件。
    • 清理:当客户端关闭连接时,清理定时器以避免内存泄漏。

注意事项

  • 浏览器支持EventSource 在现代浏览器中得到广泛支持,但在 IE 和旧版浏览器中不支持。你可能需要考虑替代方案或 Polyfill。
  • 单向通信:SSE 是单向通信,从服务器到客户端。如果需要双向通信,应该考虑使用 WebSocket。
  • 重连机制EventSource 内置了自动重连机制,连接断开时会自动尝试重新连接。
  • 带宽考虑:SSE 使用 HTTP/1.1 长连接,适合较低频率的消息推送。如果消息频率较高,应考虑 WebSocket。

通过上述示例,你应该能够理解和使用 EventSource 来实现服务器推送事件,从而在你的应用中实现实时更新。


可以使用eventSource向后端传递数据吗

EventSource 是一种用于服务器推送事件(Server-Sent Events, SSE)的技术,主要用于服务器向客户端推送数据。这是一种单向通信,从服务器到客户端。它不支持从客户端向服务器发送数据。

如果你需要双向通信(即从客户端向服务器发送数据并接收服务器的响应),有几种常见的替代方案可以考虑:

替代方案

  1. XHR (XMLHttpRequest) / Fetch API:

    • 用于在需要的时候从客户端向服务器发送请求。
    • 可以与 EventSource 配合使用,处理从服务器接收推送消息。
  2. WebSocket:

    • 支持全双工通信,允许客户端和服务器相互发送数据。
    • 适用于实时性要求较高的应用场景。

使用 Fetch API 发送数据

假设你正在使用 EventSource 接收服务器推送的数据,同时需要发送数据到服务器,你可以使用 fetch API 来实现。

前端示例:

<!DOCTYPE html>
<html>
<head><title>EventSource with Fetch</title>
</head>
<body><h1>EventSource with Fetch Example</h1><div id="messages"></div><button id="sendDataButton">Send Data</button><script>const eventSource = new EventSource('http://localhost:3000/events');eventSource.onmessage = function(event) {const messageElement = document.createElement('div');messageElement.textContent = 'Message: ' + event.data;document.getElementById('messages').appendChild(messageElement);};eventSource.onopen = function() {console.log('Connection opened.');};eventSource.onerror = function(event) {if (event.readyState === EventSource.CLOSED) {console.log('Connection closed.');} else {console.log('Error:', event);}};document.getElementById('sendDataButton').addEventListener('click', () => {fetch('http://localhost:3000/send-data', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ message: 'Hello, Server!' })}).then(response => response.json()).then(data => {console.log('Success:', data);}).catch((error) => {console.error('Error:', error);});});</script>
</body>
</html>

后端示例(Node.js + Express):

const express = require('express');
const app = express();app.use(express.json());app.get('/events', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');res.setHeader('Cache-Control', 'no-cache');res.setHeader('Connection', 'keep-alive');const intervalId = setInterval(() => {res.write(`data: ${JSON.stringify({ message: 'Hello, Client!' })}\n\n`);}, 1000);req.on('close', () => {clearInterval(intervalId);});
});app.post('/send-data', (req, res) => {const clientMessage = req.body.message;console.log('Received from client:', clientMessage);res.json({ status: 'success', receivedMessage: clientMessage });
});app.listen(3000, () => {console.log('Server listening on port 3000');
});

使用 WebSocket 实现双向通信

如果你需要更复杂的双向通信,可以考虑使用 WebSocket:

前端示例:

<!DOCTYPE html>
<html>
<head><title>WebSocket Example</title>
</head>
<body><h1>WebSocket Example</h1><div id="messages"></div><button id="sendDataButton">Send Data</button><script>const socket = new WebSocket('ws://localhost:3000');socket.onopen = function() {console.log('WebSocket connection opened.');};socket.onmessage = function(event) {const messageElement = document.createElement('div');messageElement.textContent = 'Message: ' + event.data;document.getElementById('messages').appendChild(messageElement);};socket.onerror = function(event) {console.error('WebSocket error:', event);};socket.onclose = function() {console.log('WebSocket connection closed.');};document.getElementById('sendDataButton').addEventListener('click', () => {const message = 'Hello, Server!';socket.send(message);console.log('Sent:', message);});</script>
</body>
</html>

后端示例(Node.js + ws 模块):

const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 3000 });server.on('connection', ws => {console.log('New client connected.');ws.on('message', message => {console.log('Received from client:', message);ws.send(`Hello, Client! Received your message: ${message}`);});ws.on('close', () => {console.log('Client disconnected.');});ws.send('Welcome, Client!');
});

总结

EventSource 仅用于服务器到客户端的单向通信。如果你需要从客户端向服务器发送数据,建议使用 fetchXMLHttpRequest 结合 EventSource,或者采用 WebSocket 进行双向通信。

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

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

相关文章

03-02-Vue组件之间的传值

前言 我们接着上一篇文章 03-01-Vue组件的定义和注册 来讲。 下一篇文章 04-Vue&#xff1a;ref获取页面节点–很简单 父组件向子组件传值 我们可以这样理解&#xff1a;Vue实例就是一个父组件&#xff0c;而我们自定义的组件&#xff08;包括全局组件、私有组件&#xff09;…

足球走地全自动化操作软件实现过程

本次采用selenium实现自动化操作的流程 打开浏览器录入账号密码等待数据请求&#xff08;监听&#xff09;有新数据&#xff0c;进行自动化操作通过homeName搜索&#xff0c;找到对应数据找到对应的类型&#xff08;让、大小…&#xff09;找到对应的盘口输入数量提交 附登录…

Python语法(全)

前言&#xff1a; 下面是Python基本的语法&#xff0c;大家耐心观看&#xff01; 1.基础语法 1.1字面量 字面量&#xff1a;在代码中&#xff0c;被写下来的的固定的值&#xff0c;称之为字面 1.2字符串 字符串&#xff08;string&#xff09;&#xff0c;又称文本&#xff…

Java将json字符串转为对象,保证字段顺序

一、引入依赖 <dependency><groupId>com.squareup.retrofit2</groupId><artifactId>converter-jackson</artifactId><version>2.9.0</version> </dependency>二、核心代码 public static String obj2JsonString(Object obj)…

nss做题

[NCTF 2018]签到题 1.f12在index.php中找到flag [NSSCTF 2022 Spring Recruit]ezgame 1.在js源码中就有flag [UUCTF 2022 新生赛]websign 1.打开环境后发现ctrlu和右键&#xff0c;f12都被禁用了。两种方法&#xff0c;第一种&#xff1a;禁用js&#xff1b;第二中提前打开…

【一站式学会Kotlin】第七节:kotlin匿名函数的it关键字

作者介绍: 百度资深Android工程师T6,在百度任职7年半。 目前:成立赵小灰代码工作室,欢迎大家找我交流Android、微信小程序、鸿蒙项目。= 一:通俗易懂的人工智能教程:https://www.captainbed.cn/nefu/ 点一下,打开新世界的大门。 二:【一站式学会Kotlin】免费领取:文章…

验证软件需求

1 从哪些方面验证软件需求的正确性 需求分析阶段的工作结果是开发软件系统的重要基础,大量统计数字表明,软件系统中15%的错误起源于错误的需求。为了提高软件质量,确保软件开发成功,降低软件开发成本&#xff0c;一旦对目标系统提出一组要求之后,必须严格验证这些需求的…

常用激活函数学习

常用激活函数及其应用 ReLU (Rectified Linear Unit) 公式: f ( x ) max ⁡ ( 0 , x ) f(x) \max(0, x) f(x)max(0,x)理解: 当输入值为正时&#xff0c;输出等于输入值&#xff1b;否则输出为0。ReLU函数简单且计算效率高&#xff0c;能有效缓解梯度消失问题&#xff0c;促进…

vue 表单些某项 v-if 控制后,想在显示时添加验证

效果: 可以为<el-form-item>添加 key 然后prop正常写就行 (key需要唯一值) <el-form-item label"设置" v-if"advanced_setting" key"threshold" prop"threshold"><el-inputv-model"form_Warning.threshold"p…

【退役之重学Java】关于 Gateway

一、 Gateway 是什么 Gateway 是 Spring cloud 的一个全新项目&#xff0c;基于 Spring 5 、Spring Boot 2 和 Project Reactor等技术开发的网关 旨在 是为微服务架构提供一种简单有效的统一的 API 路由管理方式 目标 是替代 Zuul 优势 性能更佳&#xff0c;Gateway 是基于 异步…

汇编小程序

汇编语言基础程序(持续更修…) 数组求和 ExitProcess PROTO.dataarr WORD 1,2,3,4,5,6,7,8,9,10 .code main PROCmov rbx, 0mov rcx, LENGTHOF arr ;获取arr元素个数mov rsi, OFFSET arr ;获取arr的首地址 Addsum:add bl, [rsi] ;获取rsi寄存器中保存地址对应的值x,…

如何使用MATLAB写测试(1)初识unittests

如何使用MATLAB写测试&#xff08;1&#xff09;初识unittests WHAT&#xff1a; 本文介绍如何在MATLAB中写简单的单元测试。 WHY&#xff1a; 在学生时代&#xff0c;我作为一名工科生喜欢用MATLAB的首要原因是可以进行快速的开发。无论是对算法的验证&#xff0c;调试&am…

【git pull 和 push详解】

git pull 和 push详解 1.背景2.命令和解释2.1 git pull简介详情 2.2 git push简介Git Push 参数及详细解释 1.背景 在分布式开发环境中&#xff0c;git pull和git push的使用确保了团队成员之间的代码一致性&#xff0c;减少了不同步导致的问题。它们简化了版本管理&#xff0c…

关于burp的intruder返回包空白问题

记录一下被自己蠢笑的问题 burp返回包为空怎么办&#xff0c;在查询无果后经过多次试验&#xff0c;确实没有效果 看那三个点还以为加载呢&#xff0c;攻击完了怎么一个显示没有 于是…… 鼠标到三个点&#xff0c;往下一拉 哈哈哈哈哈哈哈&#xff0c;真是被自己给蠢到了

[5] CUDA线程调用与存储器架构

CUDA线程调用与存储器架构 前几节简单讲了如何编写CUDA程序&#xff0c;利用GPU的处理能力并行执行多个线程和块。之前所有程序里的线程是相互独立的&#xff0c;没有多个线程之间的通信多是实际应用程序需要中间线程之间的通信&#xff0c;本文将仔细讲解线程调用以及CUDA的分…

@JsonFormat注解出现日期序列化以及反序列化问题(日期比实际日期少一天)

文章目录 前言一、场景如下所示二、问题分析三、JsonFormat注解是什么以下是 JsonFormat 注解的一些常用属性&#xff1a; 四、解决问题解决方式&#xff1a;只需要指定对应的时区就好效果如下&#xff1a; 五、JsonFormat 注解时出现日期问题总结 前言 在一次的偶然机会下发现…

Python基于PyQt6制作GUI界面——按钮

示例对应的制作的 ui文件 界面如下所示。 <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Form</class><widget class"QWidget" name"Form"><property name"geom…

ColossalAI Open-Sora 1.1 项目技术报告 (视频生成)

项目信息 项目地址&#xff1a;https://github.com/hpcaitech/Open-Sora技术报告&#xff1a; Open-Sora 1&#xff1a;https://github.com/hpcaitech/Open-Sora/blob/main/docs/report_01.mdOpen-Sora 1.1&#xff1a;https://github.com/hpcaitech/Open-Sora/blob/main/docs…

swift中json和字典Dict或者数组相互转换,JSONSerialization的强大使用

在Swift中&#xff0c;你可以使用JSONSerialization类将JSON字符串转换为字典。要将 Swift 字典转换为 JSON 字符串&#xff0c;我们可以使用JSONSerialization类的data(withJSONObject:options:)方法。这个方法将字典转换为二进制数据&#xff0c;然后我们可以使用String(data…

Day23:Leetcode:530.二叉搜索树的最小绝对差 + 501.二叉搜索树中的众数 + 236. 二叉树的最近公共祖先

LeetCode&#xff1a;530.二叉搜索树的最小绝对差 问题描述 解决方案&#xff1a; 1.思路 中序遍历 2.代码实现 class Solution {int pre;int ans;public int getMinimumDifference(TreeNode root) {ans Integer.MAX_VALUE;pre -1;dfs(root);return ans;}public void d…