XMLHttpRequest:可以從客戶端發送請求到服務器端而且獲得響應。一個小demo在這裏
但XHR不適合快速來回發送消息(如聊天室),而且沒法將這一次調用和下一次調用聯繫起來(每次發起請求,服務器都要肯定請求來自何方)。html
輪詢:瀏覽器按期向服務器發送消息並接受服務器回答是否有數據更新。(考慮輪詢間隔時間過長/太短的問題)html5
COMET(長輪詢):在每次請求的時候,服務器端保持該鏈接在一段時間內處於打開狀態,而不是在響應完成以後當即關閉。
在打開狀態的這一段時間裏,有數據更新能夠當即獲得響應。
上一個長鏈接關閉以後,瀏覽器當即打開一個新的長鏈接繼續請求。git
COMET(流):瀏覽器向服務器發送一個請求,而服務器保持鏈接打開,而後週期性向瀏覽器發送數據。github
Server-Sent events:適合服務器端向客戶端不斷的數據推送,更容易實現了comet。但整個通訊徹底單向,沒法知道瀏覽器是否響應。web
WebSocket:瀏覽器可以保持對Web服務器打開的鏈接,從而與服務器長時間交換數據。適合聊天室、大型多人遊戲、端到端寫做工具等。chrome
咱們一般說 Ajax 是一種頁面向服務器請求數據的技術,那麼 Comet 就是一種服務器向頁面推送數據的技術,讓信息以近乎實時地推送到頁面上。跨域
兩種實現 Comet 的方式:瀏覽器
先說說短輪詢的方式:
瀏覽器向服務器發出請求,打開鏈接,看有沒有更新的數據,沒有就返回空;好,一次鏈接關閉。
間隔一個輪詢時間週期,瀏覽器又再次發出請求,再看有沒有更新數據,如此反覆。
可見,這種模式效率不高,若是大多數狀況下沒有數據,仍是得不斷髮送請求。
這種實現方式很容易想到的就是 XHR + setTimeout。緩存
鑑於這樣的浪費,因而有了改善的方案——長輪詢:
瀏覽器發起一個請求,而後服務器一直打開鏈接,知道有數據更新可發送,再返回數據,關閉鏈接。
隨後又發送一個新的請求到服務器,不斷重複這一過程。
可見,這種模式減小了http請求的次數,優化了性能。服務器
But,果服務端的數據變動很是頻繁的話,這種機制和定時輪詢比較起來沒有本質上的性能的提升。
它們都有一個共同點:在瀏覽器接收數據,先對服務器發出請求。最大區別是服務器如何發送數據(當即發送/等待發送)。
流的工做過程:
瀏覽器向服務器發送一個請求,而服務器保持鏈接打開,而後週期性向瀏覽器發送數據。
這個過程,鏈接不會關閉。這就是流不一樣於輪詢的地方:它在頁面的整個生命週期中只使用了一個http鏈接。
實現方式很容易想到:利用 XHR,經過 readystatechange 事件並檢測 readyState 是否爲3進行操做。
客戶端實現:
<script> // comet http streaming 的實現 function createStreamingClient(url, progress, finished) { var xhr = new XMLHttpRequest(), received = 0; xhr.open("get", url, true); xhr.onreadystatechange = function() { var result; if (xhr.readyState == 3) { result = xhr.responseText.substring(received); received += result.length; progress(result); } else if (xhr.readyState == 4) { finished(xhr.responseText); } }; xhr.send(null); return xhr; } var client = createStreamingClient("http://localhost:3000/streaming", function(data) { alert("received:" + data); }, function(data) { alert("done"); }); </script>
var http = require("http"); var url = require("url"); http.createServer(start).listen(3000); function start(req, res) { res.writeHead(200, { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'text/html' }); var count = 0; var sid = setInterval(function(){ res.write(Math.random() + ""); if (++count == 5) { clearInterval(sid); res.end(); } }, 1000); }
'Content-Type': 'text/html'主要是爲了解決在chrome下輸出數據太少被緩存起來的問題。
這種實現方式,有兼容問題,須要針對不一樣的瀏覽器設計不一樣的方案來改進用戶體驗(IE)。
IE 的實現是經過iframe來處理:
參考《試試跨域通訊》