当前位置: 首页 > news >正文

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 进行双向通信。

相关文章:

EventSource

什么是EventSource EventSource 是一个用于服务器推送事件&#xff08;Server-Sent Events, SSE&#xff09;的接口&#xff0c;它允许服务器推送实时更新到浏览器。与 WebSocket 不同&#xff0c;SSE 是单向的&#xff08;服务器到客户端&#xff09;&#xff0c;适用于更新频…...

Vue2 Element-UI 分页组件el-pagination 修改 自带的total、跳转等默认文字

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

【简单介绍下线性回归模型】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…...

有限元法之有限元空间的构造

目录 一、区域Ω的剖分 二、三角形一次元 三、一次元的基函数与面积坐标 四、三角形二次元及其基函数 前两节我们介绍了有限元基本概念和变分理论的推导&#xff0c;本节我们继续探讨有限元空间的构造。 一、区域Ω的剖分 对矩形区域进行三角剖分&#xff0c;其中x方向剖…...

高通车规芯片分析

高通三款芯片 SA8155P 7nm SA8295P 5nm SA8255P 5nm 分析AECQ等级 AECQ100里面定义了5个工作环境温度等级&#xff1a;Grade0&#xff1a;-40-150 Grade1&#xff1a;-40-125 Grade2&#xff1a;-40-105 Grade3&#xff1a;-40-85 Grade4&#xff1a;0-70AEC-Q100整体认证测试…...

Flutter 中的 TextButton 小部件:全面指南

Flutter 中的 TextButton 小部件&#xff1a;全面指南 在Flutter的世界里&#xff0c;TextButton是一个基础的小部件&#xff0c;用于创建只包含文本的按钮。它通常用于对话框、表单以及需要强调主要操作的界面。本文将为您提供一个全面的指南&#xff0c;帮助您了解如何使用T…...

通过键值对访问字典

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

海外仓扫码管理系统怎么选?精准,高效管理需求才是核心需求

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

基于51单片机的智能灯光控制系统

一.硬件方案 智能灯光控制系统由单片机最小系统、人体感应模块、关照强度模块、灯光控制模块、电源模块和灯泡组成。本文以STC89C52单片机为核心&#xff0c;通过利用光照度和红外人体感应相结合主动与被动的探测方法&#xff0c;现了室内无人或者关照充足时灯光自动光灯&…...

测试开发面试题

简述自动化测试的三大等待 强制等待。直接使用time.sleep()方法让程序暂停指定的时间。优点是实现简单&#xff0c;缺点是不够灵活&#xff0c;可能会导致不必要的等待时间浪费。隐式等待。设置一个固定的等待时间&#xff0c;在这个时间内不断尝试去查找元素&#xff0c;如果…...

多线程JUC 第2季 BlockingQueue 阻塞队列

一 阻塞队列 1.1 阻塞队列介绍 阻塞队列&#xff08;BlockingQueue&#xff09;是一个在队列基础上又支持了两个附加操作的队列&#xff1a; put方法&#xff1a;当队列装满时&#xff0c;添加的线程则被阻塞&#xff0c;直到队列不满&#xff0c;则可用。 take方法&#x…...

【MySQL精通之路】全文搜索(3)-带查询扩展的全文搜索

博主PS&#xff1a;你可以把他理解为&#xff0c;查询猜测&#xff0c;膨胀查询&#xff0c;查询的第六感。 全文搜索支持查询扩展&#xff08;尤其是其变体“盲查询扩展”&#xff09;。 当搜索短语太短时&#xff0c;这通常很有用&#xff0c;这通常意味着用户依赖于全文搜索…...

【面试必看】Java并发

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

C++的第一道门坎:类与对象(一)

1.面向过程与面向对象 1.1面向过程 我们之前学习的C语言就是一种面向过程的语言&#xff0c;面向过程的语言强调的是具体实现的过程&#xff0c;一般用函数来具体实现。我们用面向过程的思想&#xff0c;就可以把炒菜分为以下几个步骤: 1.2面向对象 而对于面向对象的语言而言…...

经典面试题:MySQL如何调优?

目录 前言1. SQL查询优化2. 索引优化3. 表结构设计4. 硬件与配置优化5. 日常维护6. 性能测试与基准测试 前言 MySQL如何进行调优&#xff1f;这是面试中容易被问到的高频问题。 1. SQL查询优化 避免使用select* &#xff1a;只选取需要的列&#xff0c;减少数据传输量。使用…...

【程序员如何送外卖】

嘿&#xff0c;咱程序员要在美团送外卖&#xff0c;那还真有一番说道呢。 先说说优势哈&#xff0c;咱程序员那逻辑思维可不是盖的&#xff0c;规划送餐路线什么的&#xff0c;简直小菜一碟。就像敲代码找最优解一样&#xff0c;能迅速算出怎么送最省时间最有效率。而且咱平时…...

【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…...

数据挖掘导致直接路径读(direct path read)耗尽了IO

一大早就有喊业务卡的&#xff0c;检查等待事件源头&#xff0c;均为oracle写等待 查看IO负载持续维持在100%繁忙 后台有两个并行rman备份在&#xff0c;停止备份io繁忙没有好转&#xff0c;检查最近ash报告&#xff0c;发现DDTEK ODBC Oracle程序模块占用最高 检查该模块&…...

用队列实现栈 用栈实现队列 设计循环队列

用队列实现栈 思路 栈的特点&#xff1a;后进先出 队列的特点&#xff1a;先进先出 使用两个队列实现栈&#xff1a; 我们可以使用两个队列&#xff0c;一个队列为&#xff1a;空队列&#xff0c;一个队列为&#xff1a;非空队列 当我们要出队列时&#xff1a; 将 size - …...

BFS解决最短路问题(详解)

目录 BFS简介 && 框架&#xff1a; 一.二叉树的最小深度 二&#xff1a;迷宫中里入口最近的出口&#xff1a; 三.最小基因变化: 四&#xff1a;单词接龙&#xff1a; ​五&#xff1a;为高尔夫比赛砍树&#xff1a; BFS简介 && 框架&#xff1a; 说到BFS…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...