服務器發送事件(以下簡稱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
