服務器發送事件(以下簡稱SSE)是HTML 5規范的一個組成部分,可以實現服務器到客戶端的單向數據通信。通過SSE,客戶端可以自動獲取數據更新,而不用重復發送HTTP請求。一旦連接建立,“事件”便會自動被推送到客戶端。服務器端SSE通過“事件流(Event Stream)”的格式產生並推送事件。事件流對應的MIME類型為“text/event-stream”,包含四個字段:event、data、id和retry。event表示事件類型,data表示消息內容,id用於設置客戶端EventSource對象的“last event ID string”內部屬性,retry指定了重新連接的時間。
node代碼示例:
前端部分
var evtSource = new EventSource("http://localhost:3000"); let eventList = document.getElementsByTagName('body')[0] // evtSource.onmessage = function(e) { // console.log(1111,e); // var newElement = document.createElement("li"); // const eventList = document.getElementsByTagName('body')[0] // // console.log(eventList); // newElement.innerHTML = "message: " + e.data; // eventList.appendChild(newElement); // } evtSource.addEventListener("ping", function(e) { console.log(2222,e); var newElement = document.createElement("li"); let eventList = document.getElementsByTagName('body')[0] var obj = JSON.parse(e.data); newElement.innerHTML = "ping at " + obj.date; eventList.appendChild(newElement); }, false); evtSource.addEventListener("error",function(e){ console.log("服務器發送給客戶端的數據為:" + e.data); }); //只要和服務器連接,就會觸發open事件 evtSource.addEventListener("open",function(){ console.log("和服務器建立連接"); }); //處理服務器響應報文中的load事件 evtSource.addEventListener("load",function(e){ console.log("服務器發送給客戶端的數據為:" + e.data); });
服務端部分
const http = require('http') http.createServer((req, res) => { res.writeHead(200, { 'Content-Type' : 'text/event-stream', 'Access-Control-Allow-Origin':'*' }) let i = 0; const timer = setInterval(()=>{ const date = {date:new Date()} var content = 'event: ping\n'+"data:"+JSON.stringify(date)+"" + "\n\n"; res.write(content); },1000) res.connection.on("close", function(){ res.end(); clearInterval(timer); console.log("Client closed connection. Aborting."); }); }).listen(3000) console.log('server is run http://localhost:3000');
java的示例
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //媒體類型為 text/event-stream response.setContentType("text/event-stream"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); //響應報文格式為: //data:Hello World //event:load //id:140312 //換行符(/r/n) out.println("data:Hello World"); out.println("event:load"); out.println("id:140312"); out.println(); out.flush(); out.close(); }
SSE相較於輪詢具有較好的實時性,使用方法也非常簡便。然而SSE只支持服務器到客戶端單向的事件推送,而且所有版本的IE(包括到目前為止的Microsoft Edge)都不支持SSE。如果需要強行支持IE和部分移動端瀏覽器,可以嘗試EventSource Polyfill(本質上仍然是輪詢)
參考文章:
https://developer.mozilla.org/zh-CN/docs/Server-sent_events/Using_server-sent_events