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
可以监听三种类型的事件:message
、open
和 error
。
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');
});
详细解释
-
前端代码解释:
- EventSource 实例:
const eventSource = new EventSource('http://localhost:3000/events');
创建一个新的EventSource
实例,连接到服务器的/events
端点。 - 事件监听:
onmessage
处理默认的message
事件,显示从服务器接收到的消息。onopen
处理连接打开事件,输出连接已打开的信息。onerror
处理错误事件,输出错误信息或连接关闭信息。addEventListener('customEvent', ...)
处理自定义事件customEvent
,显示从服务器接收到的自定义事件数据。
- 关闭连接:使用
setTimeout
在 10 秒后关闭EventSource
连接。
- EventSource 实例:
-
后端代码解释:
- Express 服务器:创建一个简单的 Express 服务器,监听
/events
路由。 - 设置响应头:确保设置
Content-Type
,Cache-Control
, 和Connection
头以支持 SSE。 - 发送数据:
- 使用
setInterval
每秒发送一个消息。 - 使用另一个
setInterval
每 5 秒发送一个自定义事件。
- 使用
- 清理:当客户端关闭连接时,清理定时器以避免内存泄漏。
- Express 服务器:创建一个简单的 Express 服务器,监听
注意事项
- 浏览器支持:
EventSource
在现代浏览器中得到广泛支持,但在 IE 和旧版浏览器中不支持。你可能需要考虑替代方案或 Polyfill。 - 单向通信:SSE 是单向通信,从服务器到客户端。如果需要双向通信,应该考虑使用 WebSocket。
- 重连机制:
EventSource
内置了自动重连机制,连接断开时会自动尝试重新连接。 - 带宽考虑:SSE 使用 HTTP/1.1 长连接,适合较低频率的消息推送。如果消息频率较高,应考虑 WebSocket。
通过上述示例,你应该能够理解和使用 EventSource
来实现服务器推送事件,从而在你的应用中实现实时更新。
可以使用eventSource向后端传递数据吗
EventSource
是一种用于服务器推送事件(Server-Sent Events, SSE)的技术,主要用于服务器向客户端推送数据。这是一种单向通信,从服务器到客户端。它不支持从客户端向服务器发送数据。
如果你需要双向通信(即从客户端向服务器发送数据并接收服务器的响应),有几种常见的替代方案可以考虑:
替代方案
-
XHR (XMLHttpRequest) / Fetch API:
- 用于在需要的时候从客户端向服务器发送请求。
- 可以与
EventSource
配合使用,处理从服务器接收推送消息。
-
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
仅用于服务器到客户端的单向通信。如果你需要从客户端向服务器发送数据,建议使用 fetch
或 XMLHttpRequest
结合 EventSource
,或者采用 WebSocket 进行双向通信。
相关文章:
EventSource
什么是EventSource EventSource 是一个用于服务器推送事件(Server-Sent Events, SSE)的接口,它允许服务器推送实时更新到浏览器。与 WebSocket 不同,SSE 是单向的(服务器到客户端),适用于更新频…...

Vue2 Element-UI 分页组件el-pagination 修改 自带的total、跳转等默认文字
场景需求: Vue2 Element-UI 分页组件el-pagination 修改 自带的total、跳转等默认文字。如下图:默认提示字变成了英文,如何将其 变成 汉字提示呢? 解决方案: 1.方案1:修改DOM内容 不提倡此方案…...

【简单介绍下线性回归模型】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...
有限元法之有限元空间的构造
目录 一、区域Ω的剖分 二、三角形一次元 三、一次元的基函数与面积坐标 四、三角形二次元及其基函数 前两节我们介绍了有限元基本概念和变分理论的推导,本节我们继续探讨有限元空间的构造。 一、区域Ω的剖分 对矩形区域进行三角剖分,其中x方向剖…...
高通车规芯片分析
高通三款芯片 SA8155P 7nm SA8295P 5nm SA8255P 5nm 分析AECQ等级 AECQ100里面定义了5个工作环境温度等级:Grade0:-40-150 Grade1:-40-125 Grade2:-40-105 Grade3:-40-85 Grade4:0-70AEC-Q100整体认证测试…...
Flutter 中的 TextButton 小部件:全面指南
Flutter 中的 TextButton 小部件:全面指南 在Flutter的世界里,TextButton是一个基础的小部件,用于创建只包含文本的按钮。它通常用于对话框、表单以及需要强调主要操作的界面。本文将为您提供一个全面的指南,帮助您了解如何使用T…...

通过键值对访问字典
自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中,如果想将字典的内容输出也比较简单,可以直接使用print()函数。例如,要想打印dictionary字典ÿ…...

海外仓扫码管理系统怎么选?精准,高效管理需求才是核心需求
海外仓对那些想拓展国际市场的商家来说还是非常重要的,大部分的货物都需要先运到海外仓,才能继续进行下一步的物流快递发货。 那对于海外仓本身来说,当面临大量订单的时候,怎么快速的管理订单,拣选货物就变得十分重要…...

基于51单片机的智能灯光控制系统
一.硬件方案 智能灯光控制系统由单片机最小系统、人体感应模块、关照强度模块、灯光控制模块、电源模块和灯泡组成。本文以STC89C52单片机为核心,通过利用光照度和红外人体感应相结合主动与被动的探测方法,现了室内无人或者关照充足时灯光自动光灯&…...
测试开发面试题
简述自动化测试的三大等待 强制等待。直接使用time.sleep()方法让程序暂停指定的时间。优点是实现简单,缺点是不够灵活,可能会导致不必要的等待时间浪费。隐式等待。设置一个固定的等待时间,在这个时间内不断尝试去查找元素,如果…...

多线程JUC 第2季 BlockingQueue 阻塞队列
一 阻塞队列 1.1 阻塞队列介绍 阻塞队列(BlockingQueue)是一个在队列基础上又支持了两个附加操作的队列: put方法:当队列装满时,添加的线程则被阻塞,直到队列不满,则可用。 take方法&#x…...
【MySQL精通之路】全文搜索(3)-带查询扩展的全文搜索
博主PS:你可以把他理解为,查询猜测,膨胀查询,查询的第六感。 全文搜索支持查询扩展(尤其是其变体“盲查询扩展”)。 当搜索短语太短时,这通常很有用,这通常意味着用户依赖于全文搜索…...

【面试必看】Java并发
并发 1. 线程 1. 线程vs进程 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。 系统运行一个程序即是一个进程从创建,运行到消亡的过程。在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进…...

C++的第一道门坎:类与对象(一)
1.面向过程与面向对象 1.1面向过程 我们之前学习的C语言就是一种面向过程的语言,面向过程的语言强调的是具体实现的过程,一般用函数来具体实现。我们用面向过程的思想,就可以把炒菜分为以下几个步骤: 1.2面向对象 而对于面向对象的语言而言…...
经典面试题:MySQL如何调优?
目录 前言1. SQL查询优化2. 索引优化3. 表结构设计4. 硬件与配置优化5. 日常维护6. 性能测试与基准测试 前言 MySQL如何进行调优?这是面试中容易被问到的高频问题。 1. SQL查询优化 避免使用select* :只选取需要的列,减少数据传输量。使用…...

【程序员如何送外卖】
嘿,咱程序员要在美团送外卖,那还真有一番说道呢。 先说说优势哈,咱程序员那逻辑思维可不是盖的,规划送餐路线什么的,简直小菜一碟。就像敲代码找最优解一样,能迅速算出怎么送最省时间最有效率。而且咱平时…...
【git pull 和 push详解】
git pull 和 push详解 1.背景2.命令和解释2.1 git pull简介详情 2.2 git push简介Git Push 参数及详细解释 1.背景 在分布式开发环境中,git pull和git push的使用确保了团队成员之间的代码一致性,减少了不同步导致的问题。它们简化了版本管理,…...

数据挖掘导致直接路径读(direct path read)耗尽了IO
一大早就有喊业务卡的,检查等待事件源头,均为oracle写等待 查看IO负载持续维持在100%繁忙 后台有两个并行rman备份在,停止备份io繁忙没有好转,检查最近ash报告,发现DDTEK ODBC Oracle程序模块占用最高 检查该模块&…...

用队列实现栈 用栈实现队列 设计循环队列
用队列实现栈 思路 栈的特点:后进先出 队列的特点:先进先出 使用两个队列实现栈: 我们可以使用两个队列,一个队列为:空队列,一个队列为:非空队列 当我们要出队列时: 将 size - …...

BFS解决最短路问题(详解)
目录 BFS简介 && 框架: 一.二叉树的最小深度 二:迷宫中里入口最近的出口: 三.最小基因变化: 四:单词接龙: 五:为高尔夫比赛砍树: BFS简介 && 框架: 说到BFS…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...