示例:
eventSource单向通信
1. 什么是 EventSource?
EventSource 是浏览器提供的一种实现服务器推送(Server-Sent Events,简称 SSE)功能的 API。它是基于 HTTP 协议的单向通信机制,可以通过服务器将实时数据推送到客户端,而不需要客户端不断发起请求。
与传统的 AJAX 请求(如 XMLHttpRequest 或 fetch)不同,EventSource 会创建一个长连接,允许服务器主动向浏览器推送数据。这使得前端可以高效地接收实时数据,而不必通过轮询来获取更新。
为什么使用 EventSource?
- 实时性强:可以在服务器有更新时即时推送数据,而不需要客户端不断请求。
- 低延迟:相比于轮询,EventSource 更加高效,因为它不会不断地向服务器发起 HTTP 请求。
- 简洁的 API:EventSource 的用法非常简洁,只需要一行代码即可实现连接,并且可以轻松处理服务器推送的数据。
2. EventSource 的基本用法
EventSource 是通过 new EventSource(url) 创建的,参数 url 是服务器端提供的推送数据的接口。服务器会向客户端推送实时数据,并以 text/event-stream 格式传输。
基本语法
const eventSource = new EventSource('your-server-endpoint');
监听服务器发送的事件
EventSource 提供了几个事件来监听服务器端推送的消息:
- message:默认事件,接收到消息时触发。
- open:连接成功时触发。
- error:连接出错时触发。
示例代码
假设我们有一个服务器端接口 /events,该接口会定期向客户端推送消息。
// 创建 EventSource 实例
const eventSource = new EventSource('/events');// 监听连接成功事件
eventSource.addEventListener('open', function(event) {console.log('连接已成功建立');
});// 监听消息事件
eventSource.addEventListener('message', function(event) {console.log('收到消息:', event.data);
});// 监听连接出错事件
eventSource.addEventListener('error', function(event) {if (event.eventPhase == EventSource.CLOSED) {console.log('连接已关闭');} else {console.log('发生错误:', event);}
});
代码解析:
- new EventSource(‘/events’):创建与服务器的连接,/events 是服务器端的推送接口。
- eventSource.addEventListener(‘message’, callback):监听 message 事件,callback 会在接收到推送消息时执行,event.data 包含服务器发送的消息内容。
- eventSource.addEventListener(‘open’, callback):监听连接成功事件,当连接成功时会调用此回调函数。
- eventSource.addEventListener(‘error’, callback):监听错误事件,如果连接失败或被关闭,会触发该事件。
3. 服务器端的实现
在服务器端,我们需要将数据按 text/event-stream 的格式发送给客户端,通常使用一种流式的方式将数据传输给浏览器。以下是一个用 Node.js 和 Express 实现的简单 SSE 服务器示例:
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');let count = 0;setInterval(() => {count++;res.write(`data: 这是第 ${count} 条实时消息\n\n`);}, 1000);
});app.listen(3000, () => {console.log('服务器正在监听端口 3000');
});
代码解析:
res.setHeader(‘Content-Type’, ‘text/event-stream’):告诉浏览器返回的是一个事件流。
setInterval():每隔 1 秒推送一次消息,模拟服务器实时推送数据给客户端。
启动服务器并访问
启动服务器:node server.js
在浏览器中打开前端页面,监听来自 /events 接口的数据。
4. EventSource 的高级用法
自定义事件
在 SSE 中,客户端可以根据需要使用自定义事件来处理不同类型的数据,而不仅仅是 message 事件。可以使用 event 属性来定义自定义事件。
代码示例:
// 服务器端
res.write('event: customEvent\n');
res.write('data: 这是一个自定义事件\n\n');// 客户端
eventSource.addEventListener('customEvent', function(event) {console.log('收到自定义事件:', event.data);
});
自动重连
EventSource 会在连接断开后自动重连,默认重连时间为 3 秒,可以通过设置 retry 属性来指定自定义的重连时间。
代码示例:
// 服务器端
res.write('retry: 5000\n'); // 重连时间为 5000 毫秒(5秒)
关闭连接
在前端代码中,可以使用 eventSource.close() 来主动关闭连接。
eventSource.close();
5. EventSource 与其他通信技术的比较
与 WebSocket 的对比
EventSource 和 WebSocket 都可以实现服务器向客户端的实时数据推送,但它们有不同的适用场景:
- EventSource:是单向通信,适合用来从服务器向客户端推送数据,比如实时通知、新闻更新等。
- WebSocket:是双向通信,适合需要客户端和服务器之间进行双向交互的场景,如在线聊天、实时协作等。
与轮询的对比
轮询是通过定时向服务器发送请求获取最新的数据,缺点是每次都需要发起 HTTP 请求,带来不必要的开销。而 EventSource 是建立一个持久连接,服务器主动推送数据,避免了频繁的 HTTP 请求。
6. 总结
EventSource 提供了一种简单、有效的方式来实现服务器推送数据到前端。与传统的轮询相比,它能够减少请求开销,提高实时性。它也比 WebSocket 更容易实现和使用,适合单向数据流的应用场景。
优点:
- 实现简单。
- 低延迟,适合实时通知等应用。
- 自动重连功能,保证连接的稳定性。
缺点:
- 只支持单向通信,不能用于需要双向通信的场景(此时可以选择 WebSocket)。
- 浏览器支持较为有限,虽然现代浏览器普遍支持,但在一些老旧浏览器中可能无法使用。
通过使用 EventSource,开发者可以轻松地在 Web 应用中实现实时数据流功能,为用户提供更好的交互体验。