概述
前端向后端請求數據常規來說都是使用 http 連接,除非是實時性非常高的項目,例如IM系統等需要使用到WebSocket。
但是項目中有時候存在尷尬的場景:
這種實時性比較高,但是數據量比較小的內容,使用 http 輪詢會讓系統增加非常多的資源損耗,而使用 WebSocket 則顯得非常沒必要。
所以 SSE 應運而生。(事實上SSE技術產生的時間非常早)
原理
- 基于HTTP:SSE是基于HTTP的,這意味著它可以利用現有的HTTP基礎設施,如緩存、代理等。
- 單向通信:SSE是一種單向通信協議,意味著數據只能從服務器流向客戶端。這與WebSocket不同,后者支持雙向通信。
其實說白了還是 http 連接,不同的是這是一個長連接,并且返回數據的格式不太一樣,僅此而已。
SSE采用事件流格式數據,每條消息由一行或多行組成,每一行都包含字段名和值,用冒號分隔。
并且 SSE 內置的自動重連機制。如果由于任何原因連接斷開,瀏覽器會自動嘗試重新建立連接。
開發
服務端
服務端主要是需要修改請求頭,其他的就是修改一下推送信息機制。
// app/controller/sse.js
const Controller = require('egg').Controller;
class SseController extends Controller {
async stream() {
const { ctx } = this;
// 設置響應頭
ctx.set('Content-Type', 'text/event-stream');
ctx.set('Cache-Control', 'no-cache');
ctx.set('Connection', 'keep-alive');
// 發送初始連接確認消息
ctx.body = `data: Connected\n\n`;
// 可以在這里設置定時器或者其他機制來定期發送更新
const timer = setInterval(() => {
ctx.body += `data: ${new Date().toLocaleTimeString()}\n\n`;
}, 2000);
// 清理資源
ctx.res.on('close', () => {
clearInterval(timer);
});
}
}
module.exports = SseController;
客戶端
通過 EventSource 類訪問接口,實現一下數據回傳以后的邏輯。
if ('EventSource' in window) {
var eventSource = new EventSource('/api/getMessage');
// 響應數據連接
eventSource.onmessage = function(event) {
console.log('New message:', event.data);
};
// 連接異常
eventSource.onerror = function(event) {
console.error('Error occurred:', event);
eventSource.close();
};
} else {
console.log('Your browser does not support SSE.');
}
結論
其實在項目中使用 SSE 要比 WebSocket 快很多,這里說的是開發效率。
由于 SSE 是單向通信,一般來說要比 WebSocket 占用的資源更少。目前 SSE 我使用過的場景只有一個,就是已讀未讀消息的更新。
當然,有人說使用 SSE 只是將客戶端的輪詢換到了服務端,但其實并非如此。一個最根本的區別在于,輪詢即使空數據客戶端也要請求,而SSE則是有數據的時候向客戶端推送(例子不是)。
閱讀原文:原文鏈接
該文章在 2025/4/27 9:39:58 編輯過