vue3使用SSE实现前端全局事件通讯方式
作者:你的眼睛會笑
文章介绍了使用Vue3和VueUse实现基于SSE(Server-Sent Events)的全局事件通讯系统,SSE具有单向通信、基于HTTP、自动重连和轻量级等特点,适合实时性要求高的应用,实现方案包括订阅消息、取消订阅和关闭连接等功能
vue3 SSE实现前端全局事件通讯
什么是SSE (useEventSource)
SSE(Server-Sent Events)是一种基于HTTP的服务器推送技术,允许服务器单向向客户端发送事件。相比WebSocket,SSE具有以下特点:
- 单向通信(服务器→客户端)
- 基于HTTP协议,无需额外协议
- 自动重连机制
- 轻量级,实现简单
为什么选择SSE作为全局通讯方案
实时性:服务器可以即时推送数据到所有客户端低开销:相比轮询,减少了不必要的请求自动重连:内置连接恢复机制兼容性:现代浏览器普遍支持
实现方案
以下是基于Vue 3和VueUse的SSE全局通讯实现:
import { getToken } from "@/store/modules/auth/helper";
import { useEventSource } from '@vueuse/core'
import { watch } from "vue";
const baseURL = 'https://xxxxxxxxxxxx.com/api'
let eventSource: ReturnType<typeof useEventSource> | null = null;
const callbacks = new Set<(data: any) => void>();
// 初始化SSE连接
export const initSSE = () => {
if (eventSource) return;
const token = getToken();
const url = `${baseURL}/sse?Authorization=${token}`;
eventSource = useEventSource(url, [], {
autoReconnect: {
retries: 5,
delay: 5000,
onFailed() {
console.error('SSE连接失败');
}
}
});
// 错误处理
watch(eventSource.error, (err) => {
if (err) console.error('SSE连接错误:', err);
});
// 消息处理
watch(eventSource.data, (msg) => {
if (msg && msg !== 'heartbeat') {
try {
const data = JSON.parse(msg);
callbacks.forEach(cb => cb(data)); // 通知所有订阅者
} catch (e) {
console.error('SSE数据解析错误:', e);
}
}
});
};
核心功能实现
- 订阅消息
// 添加消息监听
export function addListener(callback: (data: any) => void) {
callbacks.add(callback);
return () => removeListener(callback); // 返回取消订阅函数
}
- 取消订阅
// 移除消息监听
function removeListener(callback: (data: any) => void) {
callbacks.delete(callback);
}
- 关闭连接
// 关闭SSE连接
export function closeSse() {
eventSource?.close();
eventSource = null;
callbacks.clear();
}
在Vue组件中使用
- 初始化连接
// 在应用初始化时调用
import { initSSE } from '@/utils/sse';
// 启动SSE连接
initSSE();
- 订阅消息
import { addListener,closeSse } from '@/utils/sse';
// 组件内订阅
const unsubscribe = addListener((data) => {
console.log('收到消息:', data);
// 处理业务逻辑...
});
// 组件销毁时取消订阅
onUnmounted(() => {
closeSse();
});
实际应用场景
- 实时通知系统 :新消息提醒、系统公告等
- 数据监控 :实时展示服务器状态、监控数据
- 协同编辑 :多人协作时的内容同步
- 任务进度更新 :长时间任务的进度通知
性能优化建议
- 心跳机制 :服务器定期发送心跳包保持连接
- 消息压缩 :对大消息进行压缩处理
- 批量发送 :合并多个小消息为一次发送
- 连接共享 :多个组件复用同一个连接
完整代码
// sse.ts
import { getToken } from "@/store/modules/auth/helper";
import { useEventSource } from '@vueuse/core'
import { watch } from "vue";
const baseURL = 'http://xxxxxxxxxx'
let eventSource:any = null;
const callbacks: Set<(data: any) => void> = new Set();
export const initSSE = () => {
if (eventSource) return;
const token = getToken();
const url = `${baseURL}/sse?Authorization=${token}`;
eventSource = useEventSource(url, [], {
autoReconnect: {
retries: 5,
delay: 5000,
onFailed() {
console.log('Failed to connect after 5 retries');
}
}
});
const { data, error } = eventSource;
watch(error, (err) => {
if (err) {
console.error('SSE连接错误:', err);
error.value = null;
}
});
watch(data, (msg) => {
if (msg) {
console.log('SSE接收到消息:', msg);
try {
const parsedData = JSON.parse(msg);
callbacks.forEach(cb => cb(parsedData));
} catch (e) {
console.error('SSE数据解析错误:', e);
}
data.value = null;
}
});
};
export function addListener(callback: (data: any) => void) {
callbacks.add(callback);
return () => removeListener(callback);
}
function removeListener(callback: (data: any) => void) {
callbacks.delete(callback);
}
export function closeSse() {
// eventSource?.close();
eventSource = null;
callbacks.clear();
}
总结
SSE提供了一种简单高效的服务器推送方案,非常适合构建实时性要求较高的应用。通过全局管理SSE连接,可以实现跨组件的实时通讯,减少重复连接,提高应用性能。
本文介绍的实现方案具有以下优点:
- 基于VueUse,代码简洁
- 支持自动重连
- 全局单例管理
- 易于集成到现有项目
- 对于需要双向通信的场景,可以考虑结合WebSocket或保留传统的HTTP轮询作为补充。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
