定义:允许服务器主动向浏览器推送数据的技术

方向:单向(服务器->客户端)

协议:基于HTTP,使用text/event-stream格式

特点:浏览器原生支持,自动重连

一、浏览器API:

①EventSource(标准方式)(缺点:只能GET请求,不能携带自定义headers,不能传body)

// 1. 创建连接
const eventSource = new EventSource('http://localhost:3000/sse-stream');

// 2. 监听消息
eventSource.onmessage = (event) => {
    console.log('收到数据:', event.data);
};

// 3. 监听自定义事件
eventSource.addEventListener('progress', (event) => {
    const data = JSON.parse(event.data);
    console.log('进度:', data.progress);
});

// 4. 连接打开
eventSource.onopen = () => {
    console.log('连接已建立');
};

// 5. 连接错误(会自动重连)
eventSource.onerror = (error) => {
    console.error('连接错误:', error);
};

// 6. 关闭连接
eventSource.close();

// 7. 连接状态
console.log(eventSource.readyState);
// 0 = CONNECTING
// 1 = OPEN
// 2 = CLOSED

②fetch + ReadableStream(优点:支持POST,可携带headers和body)

// 1. 发送 POST 请求(可以带 headers 和 body)
const response = await fetch(url, {
    method: 'POST',
    headers: {
        'token': 'your-token',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(data),
});

// 2. 获取流读取器
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';

// 3. 循环读取数据块
while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    // 解码数据
    buffer += decoder.decode(value, { stream: true });
    
    // 按 SSE 格式解析
    const messages = buffer.split('\n\n');
    buffer = messages.pop() || '';
    
    for (const message of messages) {
        // 解析 event 和 data
        const lines = message.split('\n');
        let eventType = '';
        let dataContent = '';
        
        for (const line of lines) {
            if (line.startsWith('event:')) {
                eventType = line.slice(6).trim();
            } else if (line.startsWith('data:')) {
                dataContent = line.slice(5).trim();
            }
        }
        
        // 处理数据
        if (eventType === 'progress') {
            const progress = parseInt(dataContent);
            // 更新进度条
        }
        
        if (eventType === 'success') {
            const result = JSON.parse(dataContent);
            // 处理成功结果
        }
    }
}

二、实际应用场景

1.文件上传进度

// 前端
const formData = new FormData();
formData.append('file', file);

const response = await fetch('/upload', {
    method: 'POST',
    body: formData,
});

const reader = response.body.getReader();
// 接收进度推送

2.AI流式对话

// 后端返回
event: message
data: {"content": "你好"}

event: message
data: {"content": ",我是"}

event: message
data: {"content": "AI助手"}

event: done
data: {"complete": true}
// 前端逐字显示
let fullText = '';
eventSource.addEventListener('message', (e) => {
    const data = JSON.parse(e.data);
    fullText += data.content;
    // 更新 UI
});

3.实时通知

// 监听通知
eventSource.addEventListener('notification', (e) => {
    const data = JSON.parse(e.data);
    showNotification(data.title, data.content);
});

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐