javascript表達行爲,css表達外觀,注意HTML既表達結構(邏輯結構),又表達內容(數據自己)一般須要更新數據時,並不須要更新結構,正是這種不改變組織結構僅改變數據的訴求,推進了數據拉取和數據推送技術的產生。javascript
SSE是一種容許服務器端向客戶端推送新數據(簡稱數據推送)的HTML5技術。數據推送有兩種替代方案:無更新方案和數據拉取方案。php
無更新方案:css
加載完畢HTML以後,獲得一個HTML頁面,以後瀏覽器會請求圖片、CSS文件和JavaScript文件等,他們都是瀏覽器能夠緩存的靜態文件。若是頁面使用後端語言,好比PHP、Ruby和Python等爲用戶動態生成HTML的語言。html
數據拉取方案:java
瀏覽器會基於一些用戶行爲,或在必定時間以後,或基於某種別的觸發方案,向服務器端請求或所有更新數據,經過javascript或一個meta標籤可以命令整個頁面從新加載。咱們所熟悉的Ajax技術只被用於請求最新數據,當收到數據時,javascript函數會利用它來局部更新DOM。數據拉取的要義:僅拉取新數據,而且只更新頁面中受影響部分。數據庫
以上的都不是數據推送,數據推送不是靜態文件,也不涉及瀏覽器爲更新數據而發起請求,數據推送是由服務器選擇客戶端發送新數據。後端
當數據源有新數據時,服務器端能馬上發送給一個或多個客戶端,而不用等客戶端來請求,這些新數據多是突發新聞、最新股票、上線朋友的聊天信息、新的天氣預報、策略遊戲中的下一步等。瀏覽器
SSE適用於更新頻繁、低延遲而且數據都是從服務端到客戶端。它和WebSocket的區別:緩存
1)便利,不須要添加任何新組件,用任何習慣的後端語言和框架就能繼續使用,不用爲新建虛擬機弄一個新的IP或新的端口號而勞神。服務器
2)服務器端的簡潔。由於SSE能在現有的HTTP/HTTPS協議上運做,因此它可以直接運行於現有的代理服務器和認證技術。
WebSocket相較SSE最大的優點在於它是雙向交流的,這意味着服務器發送數據就像從服務器接受數據同樣簡單,而SSE通常經過一個獨立的Ajax請求從客戶端向服務端傳送數據,所以相對於WebSocket使用Ajax會增長開銷。所以,若是須要以每秒一次或者更快的頻率向服務端傳輸數據,就應該用WebSocket,
具體代碼以下:
html
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>basic SSE test</title> </head> <body> <pre id = "x">initializting...</pre> <!--之因此使用pre標籤而不是p或者div是爲了確保數據能以它被接受時的格式呈現,而不會修改或格式化--> </body> <script> var es = new EventSource("basic_sse.php"); es.addEventListener("message",function(e){ //e.data document.getElementById("x").innerHTML += "\n"+e.data; },false);//使用false表示在冒泡階段處理事件,而不是捕獲階段。 </script> </html>
須要注意的是:使用服務器端數據以前最好作一下檢查,以防潛在的javascript注入攻擊。
php
<?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); $time = date('r'); echo "data: The server time is: {$time}\n\n"; flush(); ?>
「Content-Type: text/event-stream"是專門爲SSE設計的MIME類型,
效果截圖
何時數據推送是錯誤的選擇
首先考慮靜態的狀況,不引入數據推送,每當用戶打開一個頁面,在瀏覽器和服務器之間就會打開i一個套接字鏈接,服務器手機信息而後返回給用戶,可能很簡單,就像從磁盤上加載一個靜態的HTML文件或一張圖片同樣,也可能很複雜,就像要運行一段用以鏈接不少數據庫的後臺語言。這裏的關鍵點就是,一旦返回了所需的信息,套接字就會關閉,每一個HTTP請求都會打開一個這種生命週期相對較短的套接字鏈接,這些套接字是服務器上有限的資源,每當它們完成既定任務,就會被回收以循環再利用。
如今對比看一下數據推送。一個請求永遠不會完成,老是有不少信息要發送,因此套接字會一直保持打開狀態。顯然,由於它們是有限的資源,因此同一時刻的SSE鏈接數會有限制。
想象一種狀況,你在爲你最新的應用提供電話服務支持,有10個接線中心員工爲1000個用戶提供服務,用戶遇到問題,其中一個接線員接線,而後掛線。新的客戶呼叫在排隊,知道其中一個接線員掛線,這是典型的網絡服務模式。
可是,如今有個客戶打過來講,我如今沒有問題,可是接下來幾個小時都會用到大家的產品,而且若是遇到問題,我但願大家當即回覆。這個客戶將與接線員保持通話幾個小時,那麼呼叫中心的10%服務資源就被浪費。若是有10個這樣的客戶,那麼其餘990個客戶就沒法呼叫。這就是數據推送模式。
固然,這並不老是壞事,若是這個客戶一下午每隔幾秒鐘就有一個問題,這種狀況保持電話通暢不但沒有浪費10%服務資源,反而會增長。由於每一個問題都須要新打一個電話(就像數據拉取),接線員須要花額外的時間,驗證客戶身份,調出帳戶,下降服務效率。保持電話一般不只使得客戶更滿意,也會提升呼叫中心的工做效率,這就是數據推送的最適合場景。