雙向通訊之SSE

?就是我發表於2019-05-07

簡介

基於 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);
    })
});

複製程式碼

相關文章