衆所周知,AJAX的出現是前端快速發展的一個標誌,同時也是先後端得以分離的重要基礎。做爲一個C/S網絡的web系統,網絡通訊在發揮着舉足輕重的做用。
大部分的場景下,咱們是主動觸發AJAX去調取後端數據,可是總有那麼些場景是後端數據更新了再推送給前端。
本文則試着和讀者一塊兒對這個數據推送的需求進行技術方案的探究。php
首先,列一個經常使用可選的技術清單html
websocket前端
SSE(Server-Sent Event)html5
輪詢(長輪詢)web
數據推送是由服務端選擇向客戶端發送新數據。
當數據源有新數據時,服務端能馬上將它發送給一個或多個客戶端,而不用等客戶端來請求。後端
數據推送有兩種替代方案:無更新方案和數據拉取方案。
瀏覽器
數據拉取和數據推送的功能目標是一致的:讓用戶看到最新的數據。但數據推送有一些優點,即更低的延遲。
可是在數據拉取的方式中,權衡會讓你很糾結,要縮短延遲就要提升輪詢的頻次,要節省帶寬和鏈接就要下降輪詢的頻次。服務器
webSocket是html5新引入的技術,容許後臺隨時向前端發送文本或者二進制消息,WebSocket是一種全新的協議,不屬於http無狀態協議,協議名爲」ws」,
這意味着一個websocket鏈接地址會是這樣的寫法:ws://wilsonliu.cn:8080/webSocketServer
。ws不是http,因此傳統的web服務器不必定支持,
須要服務器與瀏覽器同時支持,WebSocket才能正常運行,目前的支持還不廣泛,須要特別的web服務器和現代的瀏覽器。websocket
// 在這裏略去服務端實現,着重於比較客戶端。 客戶端實現可參考[參考連接2] var ws = new WebSocket("ws://localhost:4000"); // 這裏新建一個websocket鏈接,ws此時是一個websocket句柄 ws.onopen = function(){ // 常見的前端事件回調 console.log("握手成功"); }; ws.onmessage = function(e){ // 事件有 open,close,error,message console.log("信息:" + e.data); // 輸出後臺返回的信息 }; ws.send("測試")
SSE 是 HTML5 的 Server-Sent Events
縮寫,服務器端發送的事件。網頁自動獲取服務器端的數據更新。
以前網頁獲取服務器端更新的數據是須要先想服務器發送狀況,肯定是否有數據變動,而後獲取,而SSE是服務器 一旦有數據更新就主動向網頁發送數據。網絡
// 前端 var es = new EventSource("sse.php"); // 創建鏈接,EventSource只能單向通訊,沒有send函數 es.addEventListener("message", function(e){ // EventSource有3個事件, open,error,message console.log(e.data); },false); // php <?php header("Content-Type: text/event-stream"); while(true){ echo "data:".date("Y-m-d H:i:s")."\n\n"; @ob_flush();@flush(); // 當即將數據返回給客戶端,而不是緩衝起來成批發送 sleep(1); }
輪詢:客戶端定時向服務器發送Ajax請求,服務器接到請求後立刻返回響應信息並關閉鏈接。
優勢:後端程序編寫比較容易。
缺點:請求中有大半是無用,浪費帶寬和服務器資源。
function poll() { setTimeout(function() { $.get("/path/to/server", function(data, status) { console.log(data); // 發起下一次請求 poll(); }); }, 10000); }
長輪詢:客戶端向服務器發送Ajax請求,服務器接到請求後hold住鏈接,直到有新消息才返回響應信息並關閉鏈接,客戶端處理完響應信息後再向服務器發送新的請求。
優勢:在無消息的狀況下不會頻繁的請求,耗費資源小。
缺點:服務器hold鏈接會消耗資源,返回數據順序無保證,難於管理維護。
websocket是一種更爲複雜的服務端實現技術,但它是真正的雙向傳輸技術,既能從服務端向客戶端推送數據,也能從客戶端向服務端推送數據。
websocket和SSE的瀏覽器支持率差很少。
SSE優點。
既存基礎設施優點:不須要添加任何新組件,也不須要新建虛擬機,弄一個新的IP或新的端口號。
服務端更加簡潔
文本協議,更方便調試
websocket優點
雙向數據流(使用SSE時,通常經過獨立的AJAX請求從客戶端向服務端傳送數據)
WilsonLiu's blog首發地址:http://blog.wilsonliu.cn