一、什么是SSE
SSE(Server-Sent Events)是一種基于HTTP協(xié)議的服務(wù)器推送技術(shù),允許服務(wù)器向客戶(hù)端發(fā)送實(shí)時(shí)更新。它是HTML5標(biāo)準(zhǔn)的一部分,旨在提供一種輕量級(jí)的方式,使瀏覽器能夠接收來(lái)自服務(wù)器的事件流。SSE的核心是EventSource接口,它為客戶(hù)端提供了與服務(wù)器建立單向連接的能力,從而實(shí)現(xiàn)消息的實(shí)時(shí)傳遞。

SSE的工作原理非常簡(jiǎn)單:客戶(hù)端通過(guò)HTTP請(qǐng)求向服務(wù)器發(fā)起連接,服務(wù)器在保持連接的同時(shí),持續(xù)地以文本流的形式發(fā)送事件數(shù)據(jù)??蛻?hù)端接收到數(shù)據(jù)后,可以通過(guò)JavaScript代碼處理這些事件。

SSE的主要特點(diǎn)包括:
(1)單向通信:服務(wù)器可以主動(dòng)向客戶(hù)端推送數(shù)據(jù),但客戶(hù)端無(wú)法通過(guò)同一連接向服務(wù)器發(fā)送數(shù)據(jù)。
(2)自動(dòng)重連:當(dāng)連接意外斷開(kāi)時(shí),瀏覽器會(huì)自動(dòng)嘗試重新連接。
(3)輕量級(jí)協(xié)議:基于HTTP協(xié)議,易于實(shí)現(xiàn)和調(diào)試。
(4)支持事件類(lèi)型:支持自定義事件類(lèi)型,便于對(duì)不同類(lèi)型的數(shù)據(jù)流進(jìn)行處理。

SSE非常適合大模型流式返回?cái)?shù)據(jù)的場(chǎng)景,因此很多模型服務(wù)廠商提供了SSE的接口,前端接入后可以實(shí)現(xiàn)打字機(jī)效果,實(shí)時(shí)輸出和展示大模型的回復(fù)內(nèi)容。

二、SSE和WebSocket技術(shù)對(duì)比
SSE和WebSocket都是實(shí)現(xiàn)實(shí)時(shí)通信的技術(shù),但它們的設(shè)計(jì)理念和適用場(chǎng)景存在顯著差異。

選擇SSE還是WebSocket,取決于具體的業(yè)務(wù)需求。如果只需要服務(wù)器向客戶(hù)端推送數(shù)據(jù),且對(duì)通信性能要求不高,SSE是一個(gè)簡(jiǎn)單高效的選擇;而如果需要雙向通信或?qū)π阅芤筝^高,WebSocket則更為適合。

三、標(biāo)準(zhǔn)的EventSource API
在瀏覽器中,SSE通過(guò)EventSource對(duì)象實(shí)現(xiàn)。以下是EventSource API的主要特性和用法:


1. 創(chuàng)建EventSource對(duì)象
使用EventSource對(duì)象時(shí),需要指定服務(wù)器的URL:
const eventSource = new EventSource(https://example.com/sse);


2. 事件監(jiān)聽(tīng)
EventSource支持三種事件類(lèi)型:
message:處理默認(rèn)事件。
open:連接成功時(shí)觸發(fā)。
error:連接出錯(cuò)或斷開(kāi)時(shí)觸發(fā)。
示例代碼:
eventSource.onopen = function(event) {
console.log('Connection opened:', event);
};
eventSource.onmessage = function(event) {
console.log('Message received:', event.data);
};
eventSource.onerror = function(event) {
console.error('Error occurred:', event);
};


3. 自定義事件類(lèi)型
服務(wù)器可以發(fā)送自定義事件類(lèi)型,客戶(hù)端可以通過(guò)addEventListener監(jiān)聽(tīng):
eventSource.addEventListener('custom-event', function(event) {
console.log('Custom event received:', event.data);
});


4. 關(guān)閉連接
可以通過(guò)調(diào)用close()方法手動(dòng)關(guān)閉連接:
eventSource.close();
console.log('Connection closed');


5. 服務(wù)器發(fā)送數(shù)據(jù)格式
服務(wù)器需要按照以下格式發(fā)送數(shù)據(jù):
data: Hello, World!
event: custom-event
id: 12345
retry: 3000
data:事件數(shù)據(jù)。
event:事件類(lèi)型(可選)。
id:事件ID,用于斷線(xiàn)重連時(shí)恢復(fù)狀態(tài)(可選)。
retry:指定重連間隔時(shí)間(以毫秒為單位,可選)。


四、@microsoft/fetch-event-source 介紹
@microsoft/fetch-event-source是微軟開(kāi)發(fā)的一個(gè)輕量級(jí)庫(kù),用于在Node.js和瀏覽器環(huán)境中實(shí)現(xiàn)SSE(Server-Sent Events)。與原生的EventSource相比,它提供了更多的靈活性和功能,例如支持自定義HTTP方法(如POST)、請(qǐng)求頭、認(rèn)證、請(qǐng)求體等。
npm倉(cāng)庫(kù):https://www.npmjs.com/package/@microsoft/fetch-event-source。


1. 安裝
可以通過(guò)npm或yarn安裝:
npm install @microsoft/fetch-event-source


2. 使用示例
以下是一個(gè)簡(jiǎn)單的使用示例:
import { fetchEventSource } from '@microsoft/fetch-event-source';
fetchEventSource(https://example.com/sse, {
method: POST,
headers: {
Content-Type: application/json,
Authorization: Bearer YOUR_TOKEN,
},
body: JSON.stringify({ key: value }),
onopen(response) {
if (response.ok && response.headers.get('content-type') === 'text/event-stream') {
console.log('Connection established');
} else {
console.error('Connection failed');
}
},
onmessage(event) {
console.log('Message received:', event.data);
},
onclose() {
console.log('Connection closed by server');
},
onerror(err) {
console.error('Error occurred:', err);
},
});


3. 特性
(1)支持自定義HTTP方法(如POST)。
(2)支持請(qǐng)求頭和請(qǐng)求體。
(3)提供事件鉤子(如onopen、onmessage、onclose、onerror)。
(4)支持?jǐn)嗑€(xiàn)重連。


五、@microsoft/fetch-event-source 原理解析
@microsoft/fetch-event-source的實(shí)現(xiàn)基于fetch API,通過(guò)流式處理實(shí)現(xiàn)了SSE的功能。以下是其核心實(shí)現(xiàn)原理的解析:


1. 核心邏輯
該庫(kù)的核心邏輯是使用fetch API發(fā)起HTTP請(qǐng)求,并通過(guò)ReadableStream解析服務(wù)器返回的事件流。
源碼片段(簡(jiǎn)化版):
async function fetchEventSource(url, options) {
const response = await fetch(url, options);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop(); // 保留未完整的行
for (const line of lines) {
if (line.startsWith('data:')) {
const data = line.slice(5).trim();
options.onmessage({ data });
}
}
}
options.onclose();
}


2. POST傳參的實(shí)現(xiàn)
與原生EventSource不同,該庫(kù)允許通過(guò)POST方法發(fā)送參數(shù)。實(shí)現(xiàn)方式是將請(qǐng)求體傳遞給fetch API:
fetch(url, {
method: 'POST',
headers: options.headers,
body: options.body,
});


3. 自動(dòng)重連
當(dāng)連接斷開(kāi)時(shí),庫(kù)會(huì)自動(dòng)嘗試重新連接:
setTimeout(() => {
fetchEventSource(url, options);
}, retryInterval);


4. 錯(cuò)誤處理
通過(guò)try-catch捕獲錯(cuò)誤,并調(diào)用onerror回調(diào):
try {
// 讀取流數(shù)據(jù)
} catch (err) {
options.onerror(err);
}

分享文章
微信
微博
復(fù)制鏈接

上一篇:

Web Push的隱性成本:為什么定價(jià)模式比你想的更重要

下一篇:

EngageLab深度解析:AI 驅(qū)動(dòng)的全渠道營(yíng)銷(xiāo)自動(dòng)化如何賦能業(yè)務(wù)高速增長(zhǎng)
登錄后可進(jìn)行留言,請(qǐng) 登錄注冊(cè)
0條留言
快速聯(lián)系

熱門(mén)文章

相關(guān)文章

內(nèi)容標(biāo)簽
#GPTBots

極光官方微信公眾號(hào)

關(guān)注我們,即時(shí)獲取最新極光資訊

0/140
發(fā)送

現(xiàn)在注冊(cè),領(lǐng)取新人大禮包

免費(fèi)注冊(cè)

您的瀏覽器版本過(guò)低

為了您在極光官網(wǎng)獲得最佳的訪問(wèn)體驗(yàn),建議您升級(jí)最新的瀏覽器。