更新记录
1.0.0(2025-09-23) 下载此版本
1.第一版本 2.sse使用renderjs+@microsoft/fetch-event-source实现 3.实现打印结果如图
平台兼容性
uni-app(3.7.3)
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
√ | - | √ | - | √ | - | √ | √ | - |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
- | - | - | - | - | - | - | - | - | - | - |
SSE (Server-Sent Events) 功能使用指南
效果展示
目录
概述
本项目集成了强大的 SSE (Server-Sent Events) 功能,支持 H5、Android 和 iOS 平台的实时数据推送。基于 @microsoft/fetch-event-source
库实现,提供了比原生 EventSource 更强大的功能,包括:
- ✅ 支持 GET 和 POST 请求方法
- ✅ 灵活的请求头配置
- ✅ 智能重连机制
- ✅ 自动降级到原生 EventSource
- ✅ 完整的错误处理
- ✅ 跨平台兼容性
快速开始
1. 基础用法
<template>
<view>
<!-- SSE 组件 -->
<uni-sse
ref="sse"
url="https://your-server.com/api/sse"
:headers="{ 'Authorization': `Bearer ${token}` }"
:autoConnect="true"
@message="handleMessage"
@connected="onConnected"
@error="onError"
/>
</view>
</template>
<script>
export default {
data() {
return {
token: 'your-auth-token'
}
},
methods: {
handleMessage(data) {
console.log('收到SSE消息:', data);
},
onConnected() {
console.log('SSE连接成功');
},
onError(error) {
console.error('SSE连接错误:', error);
}
}
}
</script>
2. 手动控制连接
// 手动连接
this.$refs.sse.connect();
// 断开连接
this.$refs.sse.disconnect();
// 重新连接
this.$refs.sse.reconnect();
组件介绍
UniSSE 组件
主要的 SSE 组件,位于 components/uni-sse/uni-sse.vue
核心特性:
- 使用 renderjs 实现跨平台兼容
- 基于 fetch-event-source 库
- 自动重连机制
- 完整的生命周期管理
SSE 服务管理器
全局服务管理器,位于 utils/sseService.js
功能:
- 统一的 SSE 连接管理
- 全局事件派发
- 单例模式设计
SSE 演示组件
演示和测试组件,位于 components/sse-demo/sse-demo.vue
功能:
- 实时配置和测试
- 连接状态显示
- 消息历史记录
API 参考
UniSSE 组件属性 (Props)
属性名 | 类型 | 默认值 | 必需 | 说明 |
---|---|---|---|---|
url |
String | - | ✅ | SSE 服务器地址 |
headers |
Object | {} |
❌ | 请求头配置 |
method |
String | 'GET' |
❌ | HTTP 方法 (GET/POST) |
autoConnect |
Boolean | true |
❌ | 是否自动连接 |
reconnectAttempts |
Number | 5 |
❌ | 最大重连次数 |
reconnectInterval |
Number | 3000 |
❌ | 重连间隔 (毫秒) |
UniSSE 组件事件
事件名 | 参数 | 说明 |
---|---|---|
connected |
- | 连接成功时触发 |
disconnected |
- | 连接断开时触发 |
connecting |
- | 开始连接时触发 |
disconnect |
- | 开始断开时触发 |
message |
data |
收到消息时触发 |
error |
error |
发生错误时触发 |
maxReconnectReached |
- | 达到最大重连次数时触发 |
UniSSE 组件方法
方法名 | 参数 | 返回值 | 说明 |
---|---|---|---|
connect() |
- | Boolean |
手动建立连接 |
disconnect() |
- | - | 手动断开连接 |
reconnect() |
- | - | 重新连接 |
SSE 服务管理器 API
import sseService from '@/utils/sseService.js'
// 初始化配置
sseService.init({
url: 'https://your-server.com/api/sse',
headers: { 'Authorization': 'Bearer token' },
autoConnect: true
});
// 设置组件实例
sseService.setInstance(this.$refs.uniSSE);
// 连接/断开
sseService.connect(url, headers);
sseService.disconnect();
// 事件监听
sseService.on('message', (data) => { /* 处理消息 */ });
sseService.off('message', callback);
// 获取状态
const status = sseService.getConnectionStatus();
使用示例
1. 基础 GET 请求
<template>
<uni-sse
url="https://api.example.com/sse"
method="GET"
:headers="{
'Authorization': `Bearer ${userToken}`,
'Accept': 'text/event-stream'
}"
@message="handleMessage"
/>
</template>
<script>
export default {
data() {
return {
userToken: 'your-access-token'
}
},
methods: {
handleMessage(event) {
const { id, data, type } = event;
console.log(`消息ID: ${id}, 类型: ${type}, 数据:`, data);
}
}
}
</script>
2. POST 请求示例
<template>
<uni-sse
url="https://api.example.com/sse"
method="POST"
:headers="{
'Authorization': `Bearer ${userToken}`,
'Content-Type': 'application/json'
}"
@message="handleMessage"
/>
</template>
3. 完整应用示例
<template>
<view class="app">
<!-- 连接状态指示器 -->
<view class="status-bar">
<text :class="['status', statusClass]">{{ statusText }}</text>
<button @click="toggleConnection">
{{ isConnected ? '断开' : '连接' }}
</button>
</view>
<!-- 消息显示区域 -->
<scroll-view class="messages" scroll-y>
<view v-for="(msg, index) in messages" :key="index" class="message">
<text class="time">{{ formatTime(msg.timestamp) }}</text>
<text class="content">{{ msg.content }}</text>
</view>
</scroll-view>
<!-- SSE 组件 -->
<uni-sse
ref="sseClient"
:url="sseConfig.url"
:method="sseConfig.method"
:headers="sseConfig.headers"
:autoConnect="sseConfig.autoConnect"
:reconnectAttempts="5"
:reconnectInterval="3000"
@connected="onConnected"
@disconnected="onDisconnected"
@connecting="onConnecting"
@message="onMessage"
@error="onError"
@maxReconnectReached="onMaxReconnectReached"
/>
</view>
</template>
<script>
import { mapState } from 'vuex';
export default {
data() {
return {
isConnected: false,
isConnecting: false,
messages: [],
sseConfig: {
url: '',
method: 'GET',
headers: {},
autoConnect: true
}
}
},
computed: {
...mapState(['userInfo']),
statusText() {
if (this.isConnecting) return '连接中...';
if (this.isConnected) return '已连接';
return '未连接';
},
statusClass() {
if (this.isConnecting) return 'connecting';
if (this.isConnected) return 'connected';
return 'disconnected';
}
},
created() {
this.initSSEConfig();
},
methods: {
initSSEConfig() {
this.sseConfig = {
url: 'https://your-api.com/sse',
method: 'GET',
headers: {
'Authorization': `Bearer ${this.userInfo.accessToken}`,
'Accept': 'text/event-stream'
},
autoConnect: !!this.userInfo.accessToken
};
},
toggleConnection() {
if (this.isConnected || this.isConnecting) {
this.$refs.sseClient.disconnect();
} else {
this.$refs.sseClient.connect();
}
},
onConnected() {
this.isConnected = true;
this.isConnecting = false;
uni.showToast({ title: '连接成功', icon: 'success' });
},
onDisconnected() {
this.isConnected = false;
this.isConnecting = false;
},
onConnecting() {
this.isConnecting = true;
},
onMessage(event) {
this.messages.unshift({
timestamp: Date.now(),
content: typeof event.data === 'object'
? JSON.stringify(event.data, null, 2)
: event.data,
id: event.id,
type: event.type
});
// 只保留最近 100 条消息
if (this.messages.length > 100) {
this.messages = this.messages.slice(0, 100);
}
// 处理特定类型的消息
this.handleBusinessMessage(event.data);
},
onError(error) {
console.error('SSE 错误:', error);
uni.showToast({
title: `连接错误: ${error.message}`,
icon: 'none',
duration: 3000
});
},
onMaxReconnectReached() {
uni.showModal({
title: '连接失败',
content: '已达到最大重连次数,请检查网络或服务器状态',
showCancel: false
});
},
handleBusinessMessage(data) {
if (typeof data === 'object' && data.type) {
switch (data.type) {
case 'notification':
this.showNotification(data);
break;
case 'data_update':
this.updateApplicationData(data);
break;
case 'system_alert':
this.handleSystemAlert(data);
break;
default:
console.log('未知消息类型:', data.type);
}
}
},
showNotification(data) {
uni.showToast({
title: data.title || '新消息',
icon: 'none',
duration: 2000
});
},
updateApplicationData(data) {
// 更新应用数据
this.$store.dispatch('updateData', data.payload);
},
handleSystemAlert(data) {
uni.showModal({
title: data.title || '系统通知',
content: data.message,
showCancel: false
});
},
formatTime(timestamp) {
return new Date(timestamp).toLocaleTimeString();
}
}
}
</script>
<style scoped>
.app {
height: 100vh;
display: flex;
flex-direction: column;
}
.status-bar {
padding: 20rpx;
background: #f5f5f5;
display: flex;
justify-content: space-between;
align-items: center;
}
.status {
font-size: 28rpx;
font-weight: bold;
}
.status.connected { color: #52c41a; }
.status.connecting { color: #1890ff; }
.status.disconnected { color: #999; }
.messages {
flex: 1;
padding: 20rpx;
}
.message {
margin-bottom: 20rpx;
padding: 20rpx;
background: #fff;
border-radius: 8rpx;
box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
}
.time {
display: block;
font-size: 24rpx;
color: #999;
margin-bottom: 10rpx;
}
.content {
font-size: 28rpx;
color: #333;
white-space: pre-wrap;
}
</style>
平台兼容性
H5 平台
- ✅ 完整支持 fetch-event-source 功能
- ✅ 原生 EventSource 降级支持
- ✅ 所有现代浏览器兼容
APP 平台 (Android/iOS)
- ✅ 通过 renderjs 运行在 WebView 环境
- ✅ 支持所有 fetch-event-source 功能
- ✅ 自动处理平台差异
小程序平台
- ❌ 不支持(小程序环境限制)
- 🔄 可以使用 WebSocket 或长轮询替代
配置说明
1. 基础配置
// 最小化配置
{
url: 'https://your-server.com/sse',
headers: {
'Authorization': 'Bearer your-token'
}
}
2. 完整配置
// 完整配置示例
{
url: 'https://your-server.com/api/sse',
method: 'GET', // 或 'POST'
headers: {
'Authorization': 'Bearer your-access-token',
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
'Cache-Control': 'no-cache',
'X-Custom-Header': 'custom-value'
},
autoConnect: true,
reconnectAttempts: 5,
reconnectInterval: 3000
}
3. 动态配置
// 从配置文件读取
import config from '@/common/config.js';
computed: {
sseConfig() {
return {
url: config.baseURL + config.sseURL,
headers: {
'Authorization': `Bearer ${this.userToken}`,
'Content-Type': 'application/json'
},
reconnectAttempts: config.sse?.maxReconnectAttempts || 5,
reconnectInterval: config.sse?.reconnectInterval || 3000
};
}
}
事件处理
1. 消息事件
onMessage(event) {
const { id, data, type } = event;
// 检查消息类型
if (type === 'heartbeat') {
// 心跳消息,更新连接状态
this.updateHeartbeat();
return;
}
// 处理业务消息
if (typeof data === 'object') {
this.handleStructuredMessage(data);
} else {
this.handleTextMessage(data);
}
}
2. 连接状态事件
// 连接成功
onConnected() {
console.log('SSE 连接已建立');
this.connectionStatus = 'connected';
// 可以发送连接成功的业务逻辑
this.sendConnectionNotification();
}
// 连接断开
onDisconnected() {
console.log('SSE 连接已断开');
this.connectionStatus = 'disconnected';
// 清理相关状态
this.clearPendingTasks();
}
// 连接错误
onError(error) {
console.error('SSE 连接错误:', error);
// 根据错误类型处理
if (error.message.includes('401')) {
// 认证失败,需要重新登录
this.handleAuthError();
} else if (error.message.includes('5')) {
// 服务器错误,显示提示
this.showServerErrorTip();
}
}
3. 全局事件监听
// 在 created 钩子中监听全局事件
created() {
uni.$on('sse-connected', this.onGlobalSSEConnected);
uni.$on('sse-disconnected', this.onGlobalSSEDisconnected);
uni.$on('sse-message', this.onGlobalSSEMessage);
},
// 在 beforeDestroy 钩子中移除监听
beforeDestroy() {
uni.$off('sse-connected', this.onGlobalSSEConnected);
uni.$off('sse-disconnected', this.onGlobalSSEDisconnected);
uni.$off('sse-message', this.onGlobalSSEMessage);
},
methods: {
onGlobalSSEConnected() {
// 全局 SSE 连接成功处理
},
onGlobalSSEMessage(data) {
// 全局 SSE 消息处理
}
}
错误处理和重连
1. 错误类型
错误类型 | 说明 | 处理策略 |
---|---|---|
网络错误 | 网络连接问题 | 自动重连 |
认证错误 (401/403) | Token 失效或权限不足 | 停止重连,提示重新登录 |
服务器错误 (5xx) | 服务器内部错误 | 自动重连 |
客户端错误 (4xx) | 请求参数错误 | 停止重连,检查配置 |
2. 重连策略
// 重连配置
{
reconnectAttempts: 5, // 最大重连次数
reconnectInterval: 3000, // 初始重连间隔(毫秒)
// 实际重连间隔使用指数退避算法:
// delay = min(interval * 1.5^(attempts-1), 30000)
}
3. 自定义错误处理
onError(error) {
// 错误分类处理
const errorHandlers = {
// 认证错误
401: () => {
uni.showModal({
title: '认证失败',
content: '登录已过期,请重新登录',
success: (res) => {
if (res.confirm) {
this.redirectToLogin();
}
}
});
},
// 权限错误
403: () => {
uni.showToast({
title: '权限不足',
icon: 'none'
});
},
// 服务器错误
500: () => {
uni.showToast({
title: '服务器错误,正在重试...',
icon: 'none'
});
},
// 默认错误处理
default: () => {
uni.showToast({
title: `连接错误: ${error.message}`,
icon: 'none'
});
}
};
// 提取状态码
const statusCode = this.extractStatusCode(error.message);
const handler = errorHandlers[statusCode] || errorHandlers.default;
handler();
}
服务器端实现
1. Node.js + Express
const express = require('express');
const app = express();
// 启用 CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type, Cache-Control');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
next();
});
// SSE 端点
app.get('/api/sse', (req, res) => {
// 验证认证
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token || !isValidToken(token)) {
return res.status(401).json({ error: 'Unauthorized' });
}
// 设置 SSE 响应头
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
// 发送连接确认
res.write('data: {"type":"connected","message":"SSE连接已建立"}\n\n');
// 定期发送心跳
const heartbeat = setInterval(() => {
res.write('data: {"type":"heartbeat","timestamp":' + Date.now() + '}\n\n');
}, 30000);
// 监听业务事件
const messageHandler = (data) => {
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// 注册消息监听器(假设使用 EventEmitter)
eventBus.on('user_message', messageHandler);
// 客户端断开时清理
req.on('close', () => {
clearInterval(heartbeat);
eventBus.off('user_message', messageHandler);
console.log('SSE client disconnected');
});
});
function isValidToken(token) {
// 实现 token 验证逻辑
return true; // 示例
}
2. Spring Boot (Java)
@RestController
@RequestMapping("/api")
public class SSEController {
@GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public ResponseEntity<SseEmitter> streamEvents(
@RequestHeader("Authorization") String authHeader) {
// 验证认证
String token = authHeader.replace("Bearer ", "");
if (!isValidToken(token)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
try {
// 发送连接确认
emitter.send(SseEmitter.event()
.name("connected")
.data("{\"type\":\"connected\",\"message\":\"SSE连接已建立\"}"));
// 启动心跳任务
startHeartbeat(emitter);
// 注册消息监听器
registerMessageListener(emitter);
} catch (IOException e) {
emitter.completeWithError(e);
}
return ResponseEntity.ok(emitter);
}
private void startHeartbeat(SseEmitter emitter) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(() -> {
try {
Map<String, Object> heartbeat = new HashMap<>();
heartbeat.put("type", "heartbeat");
heartbeat.put("timestamp", System.currentTimeMillis());
emitter.send(SseEmitter.event()
.name("heartbeat")
.data(heartbeat));
} catch (IOException e) {
emitter.completeWithError(e);
executor.shutdown();
}
}, 30, 30, TimeUnit.SECONDS);
}
private boolean isValidToken(String token) {
// 实现 token 验证逻辑
return true; // 示例
}
}
3. 消息格式规范
// 标准消息格式
{
"type": "message_type", // 消息类型
"id": "unique_message_id", // 消息唯一标识
"timestamp": 1640995200000, // 时间戳
"data": { // 消息数据
// 业务数据...
}
}
// 示例消息类型
{
// 连接确认
"type": "connected",
"message": "SSE连接已建立"
}
{
// 心跳消息
"type": "heartbeat",
"timestamp": 1640995200000
}
{
// 业务通知
"type": "notification",
"data": {
"title": "新消息",
"content": "您有一条新的消息",
"priority": "normal"
}
}
{
// 数据更新
"type": "data_update",
"data": {
"entity": "user_profile",
"action": "update",
"payload": { /* 更新的数据 */ }
}
}
故障排除
1. 常见问题
问题:连接建立失败
错误信息: "Failed to connect to SSE server"
解决方案:
- 检查服务器地址是否正确
- 验证网络连接
- 检查服务器是否正常运行
// 调试代码
console.log('SSE URL:', this.sseConfig.url);
console.log('请求头:', this.sseConfig.headers);
// 使用 curl 测试服务器
// curl -N -H "Accept: text/event-stream" -H "Authorization: Bearer your-token" https://your-server.com/api/sse
问题:认证失败 (401 错误)
错误信息: "Unauthorized"
解决方案:
- 检查 token 是否正确
- 验证 token 是否过期
- 确认请求头格式正确
// 检查 token
computed: {
sseHeaders() {
const token = this.$store.state.userInfo.accessToken;
console.log('当前 token:', token); // 调试用
if (!token) {
console.warn('SSE: 缺少认证 token');
return {};
}
return {
'Authorization': `Bearer ${token}`
};
}
}
问题:频繁重连
日志: "SSE reconnecting attempt 3/5"
解决方案:
- 检查服务器稳定性
- 调整重连参数
- 优化网络环境
// 调整重连配置
<uni-sse
:reconnectAttempts="3" // 减少重连次数
:reconnectInterval="5000" // 增加重连间隔
/>
2. 调试工具
启用详细日志
// 在组件中添加调试开关
data() {
return {
debugMode: process.env.NODE_ENV === 'development'
}
},
methods: {
onMessage(event) {
if (this.debugMode) {
console.log('SSE 消息详情:', {
id: event.id,
type: event.type,
data: event.data,
timestamp: Date.now()
});
}
// 处理消息...
}
}
网络请求监控
// 在浏览器开发者工具中
// 1. 打开 Network 标签页
// 2. 筛选 "EventStream" 类型的请求
// 3. 查看请求详情和响应流
性能监控
// 监控连接性能
const connectionStart = Date.now();
onConnected() {
const connectionTime = Date.now() - connectionStart;
console.log(`SSE 连接耗时: ${connectionTime}ms`);
}
3. 错误码对照表
错误码 | 说明 | 解决方案 |
---|---|---|
400 | 请求格式错误 | 检查请求参数和格式 |
401 | 认证失败 | 检查 token 有效性 |
403 | 权限不足 | 确认用户权限 |
404 | 端点不存在 | 检查 URL 路径 |
429 | 请求过频 | 减少连接频率 |
500 | 服务器内部错误 | 联系服务器管理员 |
502 | 网关错误 | 检查服务器代理配置 |
503 | 服务不可用 | 等待服务恢复 |
最佳实践
1. 连接管理
// ✅ 好的做法:统一连接管理
export default {
data() {
return {
sseConnected: false
}
},
created() {
// 监听用户登录状态
this.$store.watch(
(state) => state.userInfo.accessToken,
(newToken, oldToken) => {
if (newToken && !oldToken) {
// 用户登录,建立 SSE 连接
this.connectSSE();
} else if (!newToken && oldToken) {
// 用户登出,断开 SSE 连接
this.disconnectSSE();
}
}
);
},
methods: {
connectSSE() {
if (this.$refs.sse && !this.sseConnected) {
this.$refs.sse.connect();
}
},
disconnectSSE() {
if (this.$refs.sse && this.sseConnected) {
this.$refs.sse.disconnect();
}
}
}
}
2. 消息处理
// ✅ 好的做法:结构化消息处理
methods: {
handleMessage(event) {
const { data } = event;
// 验证消息格式
if (!data || typeof data !== 'object') {
console.warn('SSE: 收到无效消息格式', data);
return;
}
// 根据消息类型路由处理
const handlers = {
'notification': this.handleNotification,
'data_update': this.handleDataUpdate,
'system_alert': this.handleSystemAlert,
'heartbeat': this.handleHeartbeat
};
const handler = handlers[data.type];
if (handler) {
handler(data);
} else {
console.warn('SSE: 未知消息类型', data.type);
}
},
handleNotification(data) {
// 显示通知
uni.showToast({
title: data.title,
icon: 'none'
});
},
handleDataUpdate(data) {
// 更新本地数据
this.$store.dispatch('updateData', data.payload);
}
}
3. 错误处理
// ✅ 好的做法:优雅的错误处理
methods: {
onError(error) {
// 记录错误日志
this.logError('SSE_ERROR', {
message: error.message,
timestamp: Date.now(),
userAgent: navigator.userAgent
});
// 用户友好的错误提示
const userFriendlyMessage = this.getUserFriendlyErrorMessage(error);
this.showErrorNotification(userFriendlyMessage);
// 根据错误类型决定是否重试
if (this.shouldRetry(error)) {
this.scheduleRetry();
} else {
this.handleFatalError(error);
}
},
getUserFriendlyErrorMessage(error) {
const errorMessages = {
'network': '网络连接失败,请检查网络设置',
'auth': '认证失败,请重新登录',
'server': '服务器暂时不可用,请稍后重试',
'default': '连接出现问题,正在尝试重新连接'
};
const errorType = this.classifyError(error);
return errorMessages[errorType] || errorMessages.default;
}
}
4. 性能优化
// ✅ 好的做法:性能优化
export default {
data() {
return {
messageBuffer: [], // 消息缓冲区
processingMessages: false
}
},
methods: {
onMessage(event) {
// 将消息添加到缓冲区
this.messageBuffer.push(event);
// 批量处理消息,避免阻塞 UI
if (!this.processingMessages) {
this.processingMessages = true;
this.$nextTick(() => {
this.processMessageBuffer();
this.processingMessages = false;
});
}
},
processMessageBuffer() {
const messages = this.messageBuffer.splice(0);
messages.forEach(message => {
this.handleSingleMessage(message);
});
},
handleSingleMessage(message) {
// 处理单条消息
try {
this.processBusinessLogic(message);
} catch (error) {
console.error('处理消息时出错:', error);
}
}
},
beforeDestroy() {
// 确保清理资源
this.messageBuffer = [];
if (this.$refs.sse) {
this.$refs.sse.disconnect();
}
}
}
5. 测试建议
// ✅ 测试用例示例
describe('SSE 功能测试', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(SSEComponent, {
propsData: {
url: 'ws://localhost:3000/sse',
autoConnect: false
}
});
});
test('应该能够成功建立连接', async () => {
wrapper.vm.connect();
await wrapper.vm.$nextTick();
expect(wrapper.vm.isConnected).toBe(true);
});
test('应该能够接收和处理消息', async () => {
const mockMessage = {
id: '123',
data: { type: 'test', content: 'hello' },
type: 'message'
};
wrapper.vm.onMessage(mockMessage);
expect(wrapper.vm.messages).toContain(mockMessage);
});
test('应该能够优雅地处理连接错误', async () => {
const mockError = { message: 'Connection failed' };
wrapper.vm.onError(mockError);
expect(wrapper.vm.error).toEqual(mockError);
});
});
技术支持
如果在使用过程中遇到问题,请:
- 查看浏览器开发者工具的 Console 和 Network 标签页
- 检查服务器端的日志
- 参考本文档的故障排除部分
- 使用测试页面
/pages/sse-test/sse-test
进行调试
更多技术细节请参考:
版本信息:
- 文档版本: 1.0.0
- 最后更新: 2024年12月
- 适用平台: H5, Android, iOS