簡介
基於 HTTP 協議,一個客戶端去從伺服器端訂閱一條流,之後服務端可以傳送訊息給客戶端直到服務端或者客戶端關閉該“流”
特點
- 建立瀏覽器與伺服器之間的通訊渠道,然後伺服器向瀏覽器推送資訊
- SSE 是單向通道,只能伺服器向瀏覽器傳送,因為流資訊本質上就是下載
- 使用 HTTP 協議,現有的伺服器軟體都支援。WebSocket 是一個獨立協議。
- 屬於輕量級,使用簡單,相容性良好
客戶端
let eventSource = new EventSource('/clock'); // url可以同域,也可以跨域
let clock = document.querySelector("#clock");
// 連線開啟
source.onopen = function (event) {
// ...
};
// 監聽伺服器返回的訊息
eventSource.onmessage = (e) => {
let message = e.data;
clock.innerHTML = message;
}
// 監聽連線請求失敗
eventSource.onerror = function(err){
console.log(err);
}
// 關連線
eventSource.close();
// 監聽自定義事件
eventSource.addEventListener('foo', function (e) {
var data = e.data;
}, false);
複製程式碼
伺服器端
- 事件流對應MIME格式為text/event-stream,而且其基於HTTP長連線。針對HTTP1.1規範預設採用長連線,針對HTTP1.0的伺服器需要特殊設定。
- event-source必須編碼成utf-8的格式
- 每一次傳送的資訊,由若干個message組成,每個message之間用\n\n分隔。每個message內部由若干欄位組成,每一欄位都是如下格式。
[field]: value\n
複製程式碼
field需要使用下面4個規範定義好的欄位:
Event: 自定義事件型別
Data: 傳送的資料
ID: 每一條事件流的ID
Retry: 告知瀏覽器在所有的連線丟失之後重新開啟新的連線等待的時間,在自動重新連線的過程中,之前收到的最後一個事件流ID會被髮送到服務端
複製程式碼
使用例子:
app.get('/clock', (req, res) => {
res.header('Content-Type', 'text/event-stream'); // 特定
let timer = setInterval(() => {
res.write(`id:${counter++}\nevent:message\ndata:${new Date().toLocaleDateString()}\n\n`);
}, 1000);
res.on('close', () => {
clearInterval(timer);
})
});
複製程式碼