服務器發送事件簡介
當 Web 開發世界為 Web Sockets 的“令人興奮的未來”而熱議時,還有一個與我相同的規範讓我更加興奮:服務器發送事件。該規範基於最初稱為服務器發送的 DOM 事件並在 Opera 9 中實現的功能。這個想法非常簡單:網頁可以訂閱服務器生成的事件流。每當服務器上發生事件時,都會向客戶端發送通知並生成 JavaScript 事件。
與 Web Socket 的區別
Web Sockets 和 Server-Sent Events 最大的區別在於前者是雙向的,而後者不是。顧名思義,服務器發送事件僅從服務器發送到瀏覽器。如果您希望向服務器發送數據,則必須通過另一種機制來完成,例如 XMLHttpRequest
.
第二個相當大的區別是服務器發送的事件是通過普通的舊 HTTP 發送的,沒有任何修改。這對實施者來說是個好消息,因為除了確保高持續時間的請求不會使您的服務器崩潰之外,服務器上不會有任何變化。使用 HTTP 可確保服務器發送的事件不會受到仍然圍繞 Web Sockets 旋轉的相同協議焦慮的阻礙。
API
服務器發送事件的 JavaScript API 與 Web 套接字的 API 非常相似。要訂閱新的事件流,首先要創建一個新的 EventSource 對象並傳入入口點:
var source = new EventSource("myevents.php");
請注意,引用的 URL 必須與創建對象的頁面位於同一來源(方案、域和端口)。 EventSource
實例有一個 readyState
屬性設置為 0 表示它正在連接到服務器,1 表示打開的連接,2 表示關閉的連接。
還有三個事件:open
,在建立連接時觸發,message
,當從服務器接收到新事件時觸發,並且 error
,當無法建立連接時觸發。在一般用法中,onmessage
事件處理程序可能是您使用最多的一個:
source.onmessage = function(event){
var data = event.data;
};
服務器發回的信息通過event.data
返回 作為一個字符串。
默認情況下,EventSource
對象將嘗試保持與服務器的連接。您可以通過調用 close() 方法強制對象立即斷開連接並停止嘗試重新連接:
source.close();
事件流
服務器事件通過 MIME 類型為 text/event-stream
的長期 HTTP 請求發送 .響應的格式是純文本,最簡單的形式是由前綴 data:
組成 後跟文字,如:
data: foo
data: bar
data: foo
data: bar
此流的第一部分觸發 message
event.data
的事件 設置為“foo”;第二部分觸發 message
event.data
的事件 設置為“酒吧”;第三個觸發 message
event.data
的事件 設置為“foo\nbar”(注意中間的換行符)。當有兩個或多個以 data:
開頭的連續行時 ,它被解釋為多行數據,並且值與換行符連接在一起。在包含 data:
的行之後遇到空行之前,永遠不會觸發消息事件 ,所以在服務器上生成事件流時一定要包含那個額外的換行符。
您還可以通過包含 id:
將 ID 與特定事件相關聯 data:
之前或之後的行 行:
data: foo
id: 1
通過設置 ID,EventSource
對象跟踪最後觸發的事件。如果連接斷開,一個名為 Last-Event-ID
的特殊 HTTP 標頭 與請求一起發送,以便服務器可以確定下一個適合觸發的事件。
總結
Server-Sent 事件是用於服務器推送技術的 Web Sockets 的一種更簡單的替代方案。儘管有些人似乎確信雙向通信是絕對必要的,但許多提議的 Web Sockets 用例實際上可以使用服務器發送的事件來實現。這包括流股票報價、遊戲分數更新、拍賣投標更新等。Opera 10.7 有一個服務器發送事件的實現,並且一個實現也已經進入了 WebKit 存儲庫。在加入 Web Sockets 潮流之前,請考慮一下 Server-Sent Events 是否可以完成相同的任務。
更新(2010 年 10 月 22 日): 修正錯字。