跳至主要内容

2 篇文章 含有標籤「SSE」

檢視所有標籤

EventSource API in JavaScript 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

前言

在現代的網頁應用程式中,實時性資料更新是一個常見需求,例如即時通知、股價更新、聊天室訊息、伺服器狀態監控等。傳統上,開發者可能會透過輪詢(Polling)或 WebSocket 來實現。然而,若只是單向由伺服器推送訊息到瀏覽器端,其實有更簡單且高效的選擇:EventSource API

EventSource 基於 Server-Sent Events(SSE),由伺服器主動推送文字資料到客戶端,並且使用 HTTP 協議的持久連線,開發上比 WebSocket 更簡單,適合事件流的場景。本文將帶我們快速入門 EventSource API,理解它的特性與應用方式。


重點摘要

  1. EventSource 與 SSE 的核心概念

    • EventSource 是瀏覽器提供的 JavaScript API,用於接收伺服器推送的 SSE(Server-Sent Events)。
    • 採用 HTTP 長連線,不需要 WebSocket,也不需要額外協議。
    • 支援自動重連(瀏覽器會自動在連線中斷時重新連接伺服器)。
  2. EventSource 的適用場景

    • 即時通知(系統提醒、訊息推送)
    • 資料更新(股價、天氣、賽事比分)
    • 記錄串流(伺服器日誌、事件追蹤)
    • 聊天室訊息(單向推送)
  3. EventSource 的特性

    • 單向通訊:伺服器 → 客戶端
    • 自動重連機制(可透過伺服器端 retry: 指令調整重試時間)
    • 基於純文字的事件格式(MIME type 為 text/event-stream
    • 可透過自訂事件名稱分發不同事件
  4. 與其他技術比較

    • Polling:需要客戶端頻繁請求,耗費頻寬與伺服器資源。
    • WebSocket:雙向溝通更靈活,但需要額外處理協議與狀態管理。
    • EventSource(SSE):單向推送即可,實作簡單、輕量化,適合多數即時通知場景。

EventSource 使用範例

1. 瀏覽器端(JavaScript)

// 建立 EventSource 連線
const eventSource = new EventSource('/events');

// 接收預設訊息(message 事件)
eventSource.onmessage = function (event) {
console.log('收到訊息:', event.data);
};

// 接收自訂事件
eventSource.addEventListener('news', function (event) {
console.log('收到新聞事件:', event.data);
});

// 監控錯誤與連線狀態
eventSource.onerror = function (error) {
console.error('EventSource 發生錯誤:', error);
};

2. 伺服器端(Node.js Express 範例)

const express = require('express');
const app = express();

app.get('/events', (req, res) => {
// 設定 SSE 必要的 Header
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');

// 每隔 3 秒推送一個訊息
const intervalId = setInterval(() => {
const data = new Date().toLocaleTimeString();
res.write(`data: 現在時間 ${data}\n\n`);
}, 3000);

// 當客戶端中斷連線時清理資源
req.on('close', () => {
clearInterval(intervalId);
});
});

app.listen(3000, () => {
console.log('SSE 伺服器運行於 http://localhost:3000/events');
});

3. SSE 資料格式範例

伺服器回傳的資料需符合 text/event-stream 格式,每筆訊息以兩個換行結尾。

data: 這是一個預設訊息

event: news
data: 這是一個新聞更新

event: alert
data: 系統警告訊息
retry: 5000

說明:

  • data::主要訊息內容,可以有多行。
  • event::指定自訂事件名稱,客戶端可用 addEventListener 監聽。
  • retry::定義自動重連的延遲時間(毫秒)。

注意事項

  1. 瀏覽器支援性:大部分現代瀏覽器支援 EventSource(IE 除外)。
  2. 跨域問題:若伺服器與前端不同網域,需設定 CORS。
  3. 資料格式:僅支援 UTF-8 文字資料,若要傳送二進位資料需轉成 Base64 或 JSON。
  4. 連線數限制:部分瀏覽器對同一網域的 SSE 連線數有限制(通常 6 條)。
  5. 斷線重連:內建自動重連機制,但若伺服器返回錯誤狀態碼,可能需手動處理。

總結

EventSource API 提供了一個簡單又高效的方式,讓前端應用程式能夠輕鬆接收伺服器的即時推送。相較於 WebSocket,EventSource 不需要額外的協議處理,也避免了頻繁輪詢帶來的效能浪費。在僅需單向資料更新的場景下,它是一個理想解決方案。

當我們下次需要在前端實現即時通知、動態更新數據或流式資料顯示時,不妨先考慮 EventSource,它或許就是最輕量的選擇。

Server-Sent Events(SSE)入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

前言

在現代 Web 應用中,即時資料傳輸已經成為重要需求,例如股票行情更新、聊天室訊息、即時通知等。傳統的 HTTP 請求模式是 客戶端發起請求,伺服器回應一次,這種「單向請求-回應」模式無法有效支持持續更新。

WebSocket 是一個廣為人知的解決方案,提供全雙工通道,但對於單向更新(伺服器推送到客戶端)而言,WebSocket 可能略顯複雜。這時,Server-Sent Events(SSE) 就是一個簡單、輕量級的替代方案。SSE 提供 伺服器到客戶端的單向持續資料推送,使用原生 HTML5 技術即可實現,不需額外協議或第三方套件。


SSE 的核心概念

Server-Sent Events 是基於 HTTP 協議,透過 text/event-stream 的 MIME 類型,保持一個持久連接,讓伺服器可以不斷地向客戶端傳送資料。SSE 的主要特性包括:

  1. 單向通訊

    • 伺服器向客戶端推送資料,客戶端只能接收。若需要雙向通訊,仍需搭配 WebSocket 或 AJAX 請求。
  2. 自動重連

    • 客戶端若因網路斷線或其他原因中斷,瀏覽器會自動重連,可透過 retry 指定重連間隔。
  3. 文字格式傳輸

    • SSE 傳輸的資料以純文字格式為主,每個事件用特定的格式標記(如 event:data:id: 等)。
  4. 支援事件命名

    • 可以自定義事件名稱,在前端監聽不同事件,提高可讀性與維護性。
  5. 輕量且易實作

    • 客戶端只需使用 JavaScript 的 EventSource API,即可快速建立 SSE 連接。

重點摘要

  • 單向連接:伺服器 → 客戶端

  • 持久連接:不需每次重新建立 HTTP 請求

  • 事件格式event, data, id, retry

  • 自動重連:瀏覽器自動處理連線中斷

  • 瀏覽器支援:大部分現代瀏覽器原生支援(IE 除外)

  • 適用場景

    • 即時通知系統
    • 資料更新流(股票、天氣、社群消息)
    • 運行狀態監控儀表板

SSE 的資料格式

SSE 的資料格式遵循 行為約定

id: 1
event: message
retry: 3000
data: Hello, this is a message from server

說明:

  • id(選填):事件 ID,客戶端斷線後重連,會告訴伺服器最後接收的 ID
  • event(選填):事件名稱,自訂事件類型
  • retry(選填):重連間隔,單位為毫秒
  • data(必填):事件資料內容,可有多行

注意:每個事件以空行結束,代表事件結束。


SSE 實作範例

以下示範如何使用 Node.js + Express 建立 SSE 服務,並在前端接收事件:

1. 後端 (Node.js + Express)

const express = require('express');
const app = express();

app.get('/events', (req, res) => {
// 設定 SSE 標頭
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');

let counter = 0;

// 每秒推送一次訊息
const interval = setInterval(() => {
counter++;
res.write(`id: ${counter}\n`);
res.write(`event: message\n`);
res.write(`data: {"count": ${counter}, "time": "${new Date().toISOString()}"}\n\n`);
}, 1000);

// 當客戶端斷線時清理 interval
req.on('close', () => {
clearInterval(interval);
});
});

app.listen(3000, () => {
console.log('SSE server running on http://localhost:3000');
});

2. 前端 (HTML + JavaScript)

<!DOCTYPE html>
<html>
<head>
<title>SSE Example</title>
</head>
<body>
<h1>Server-Sent Events Demo</h1>
<div id="messages"></div>

<script>
const eventSource = new EventSource('http://localhost:3000/events');

eventSource.onmessage = function (event) {
const msgDiv = document.getElementById('messages');
const data = JSON.parse(event.data);
msgDiv.innerHTML += `<p>Count: ${data.count}, Time: ${data.time}</p>`;
};

eventSource.addEventListener('message', function (event) {
// 也可透過自訂事件名稱接收
console.log('Received event:', event.data);
});

eventSource.onerror = function (err) {
console.error('EventSource failed:', err);
};
</script>
</body>
</html>

解釋

  • EventSource 會自動建立持久連接
  • 每次後端 res.write 新事件時,前端 onmessage 會被觸發
  • 客戶端不需發起額外請求,伺服器可以持續推送

SSE 與 WebSocket 的比較

特性SSEWebSocket
通訊方向伺服器 → 客戶端(單向)雙向(伺服器 ↔ 客戶端)
協議HTTPTCP / WebSocket protocol
連接維護自動重連需手動處理斷線
輕量實作非常簡單相對複雜
適用場景事件推送、資料流即時遊戲、聊天室、雙向互動

實務應用建議

  1. 適用場景:單向更新、事件通知、儀表板數據刷新

  2. 不適用場景:需要大量雙向互動、低延遲遊戲或高頻交易

  3. 瀏覽器支援:大部分現代瀏覽器支援,但 IE 需 polyfill

  4. 部署注意

    • 長連接可能對 Nginx / Proxy 設定有影響,需允許長時間 HTTP keep-alive
    • 伺服器端要注意資源釋放,避免記憶體泄漏

結論

Server-Sent Events 是一種 簡單、輕量、易於實作的即時資料推送方案,特別適合需要 單向事件更新 的 Web 應用。對於需要雙向通訊的場景,WebSocket 或其他方案可能更合適。掌握 SSE 可以讓我們在開發即時應用、監控儀表板或通知系統時快速上手,並結合現代瀏覽器的原生支援,提供穩定的即時體驗。