示例:
eventSource單向通信
1. 什么是 EventSource?
EventSource 是瀏覽器提供的一種實現服務器推送(Server-Sent Events,簡稱 SSE)功能的 API。它是基于 HTTP 協議的單向通信機制,可以通過服務器將實時數據推送到客戶端,而不需要客戶端不斷發起請求。
與傳統的 AJAX 請求(如 XMLHttpRequest 或 fetch)不同,EventSource 會創建一個長連接,允許服務器主動向瀏覽器推送數據。這使得前端可以高效地接收實時數據,而不必通過輪詢來獲取更新。
為什么使用 EventSource?
- 實時性強:可以在服務器有更新時即時推送數據,而不需要客戶端不斷請求。
- 低延遲:相比于輪詢,EventSource 更加高效,因為它不會不斷地向服務器發起 HTTP 請求。
- 簡潔的 API:EventSource 的用法非常簡潔,只需要一行代碼即可實現連接,并且可以輕松處理服務器推送的數據。
2. EventSource 的基本用法
EventSource 是通過 new EventSource(url) 創建的,參數 url 是服務器端提供的推送數據的接口。服務器會向客戶端推送實時數據,并以 text/event-stream 格式傳輸。
基本語法
const eventSource = new EventSource('your-server-endpoint');
監聽服務器發送的事件
EventSource 提供了幾個事件來監聽服務器端推送的消息:
- message:默認事件,接收到消息時觸發。
- open:連接成功時觸發。
- error:連接出錯時觸發。
示例代碼
假設我們有一個服務器端接口 /events,該接口會定期向客戶端推送消息。
// 創建 EventSource 實例
const eventSource = new EventSource('/events');// 監聽連接成功事件
eventSource.addEventListener('open', function(event) {console.log('連接已成功建立');
});// 監聽消息事件
eventSource.addEventListener('message', function(event) {console.log('收到消息:', event.data);
});// 監聽連接出錯事件
eventSource.addEventListener('error', function(event) {if (event.eventPhase == EventSource.CLOSED) {console.log('連接已關閉');} else {console.log('發生錯誤:', event);}
});
代碼解析:
- new EventSource(‘/events’):創建與服務器的連接,/events 是服務器端的推送接口。
- eventSource.addEventListener(‘message’, callback):監聽 message 事件,callback 會在接收到推送消息時執行,event.data 包含服務器發送的消息內容。
- eventSource.addEventListener(‘open’, callback):監聽連接成功事件,當連接成功時會調用此回調函數。
- eventSource.addEventListener(‘error’, callback):監聽錯誤事件,如果連接失敗或被關閉,會觸發該事件。
3. 服務器端的實現
在服務器端,我們需要將數據按 text/event-stream 的格式發送給客戶端,通常使用一種流式的方式將數據傳輸給瀏覽器。以下是一個用 Node.js 和 Express 實現的簡單 SSE 服務器示例:
const express = require('express');
const app = express();app.get('/events', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');res.setHeader('Cache-Control', 'no-cache');res.setHeader('Connection', 'keep-alive');let count = 0;setInterval(() => {count++;res.write(`data: 這是第 ${count} 條實時消息\n\n`);}, 1000);
});app.listen(3000, () => {console.log('服務器正在監聽端口 3000');
});
代碼解析:
res.setHeader(‘Content-Type’, ‘text/event-stream’):告訴瀏覽器返回的是一個事件流。
setInterval():每隔 1 秒推送一次消息,模擬服務器實時推送數據給客戶端。
啟動服務器并訪問
啟動服務器:node server.js
在瀏覽器中打開前端頁面,監聽來自 /events 接口的數據。
4. EventSource 的高級用法
自定義事件
在 SSE 中,客戶端可以根據需要使用自定義事件來處理不同類型的數據,而不僅僅是 message 事件。可以使用 event 屬性來定義自定義事件。
代碼示例:
// 服務器端
res.write('event: customEvent\n');
res.write('data: 這是一個自定義事件\n\n');// 客戶端
eventSource.addEventListener('customEvent', function(event) {console.log('收到自定義事件:', event.data);
});
自動重連
EventSource 會在連接斷開后自動重連,默認重連時間為 3 秒,可以通過設置 retry 屬性來指定自定義的重連時間。
代碼示例:
// 服務器端
res.write('retry: 5000\n'); // 重連時間為 5000 毫秒(5秒)
關閉連接
在前端代碼中,可以使用 eventSource.close() 來主動關閉連接。
eventSource.close();
5. EventSource 與其他通信技術的比較
與 WebSocket 的對比
EventSource 和 WebSocket 都可以實現服務器向客戶端的實時數據推送,但它們有不同的適用場景:
- EventSource:是單向通信,適合用來從服務器向客戶端推送數據,比如實時通知、新聞更新等。
- WebSocket:是雙向通信,適合需要客戶端和服務器之間進行雙向交互的場景,如在線聊天、實時協作等。
與輪詢的對比
輪詢是通過定時向服務器發送請求獲取最新的數據,缺點是每次都需要發起 HTTP 請求,帶來不必要的開銷。而 EventSource 是建立一個持久連接,服務器主動推送數據,避免了頻繁的 HTTP 請求。
6. 總結
EventSource 提供了一種簡單、有效的方式來實現服務器推送數據到前端。與傳統的輪詢相比,它能夠減少請求開銷,提高實時性。它也比 WebSocket 更容易實現和使用,適合單向數據流的應用場景。
優點:
- 實現簡單。
- 低延遲,適合實時通知等應用。
- 自動重連功能,保證連接的穩定性。
缺點:
- 只支持單向通信,不能用于需要雙向通信的場景(此時可以選擇 WebSocket)。
- 瀏覽器支持較為有限,雖然現代瀏覽器普遍支持,但在一些老舊瀏覽器中可能無法使用。
通過使用 EventSource,開發者可以輕松地在 Web 應用中實現實時數據流功能,為用戶提供更好的交互體驗。