接上文AJAX實現跨域的幾種方法(一)
這一篇是關于Comet和Web Sockets的筆記。
2.4 Comet
Ajax是一種從頁面向服務器請求數據的技術,而Comet則是一種服務器向頁面推送數據的技術。
Comet能夠讓信息近乎實時的被推送到頁面上,非常適合處理體育比賽的分數和股票報價。
有兩種實現Comet的方式:長輪詢和流。
2.4.1 長輪詢
長輪詢是短輪詢(瀏覽器定時向服務器發送請求,看有沒有更新的數據)的一個翻版。
所謂長輪詢指的是
頁面發起一個到服務器的請求,然后服務器一直保持連接打開,直到有數據可發送。發送完數據后,瀏覽器關閉連接,隨即又發送一個到服務器的新請求。這一過程在頁面打開期間一直持續不斷。
無論是短輪詢還是長輪詢,瀏覽器都要在接收數據之前,先發起對服務器的連接。兩者最大的區別在于服務器如何發送數據。
- 短輪詢是服務器立即發送響應,無論數據是否有效。
- 長輪詢時等待發送響應。
輪詢的優勢是所有瀏覽器都支持,因為使用XHR
對象和setTimeOut()
就能實現。而程序員要做的就是決定什么時候發送請求。
2.4.2 HTTP流
流不同于上述兩種輪詢,因為它在頁面的整個生命周期內只用一個HTTP連接。具體來說,就是瀏覽器向服務器發送一個請求,而服務器保持連接打開,然后周期性的向瀏覽器發送數據。
所有服務器端語言都支持打印到輸出緩存然后刷新(將輸出緩存中的內容一次性全部發送到客戶端)的功能,而這正是實現HTTP流的關鍵所在。
在FireFox、Safari、Opera和Chrome中,通過偵聽readystatechange
事件及檢測readyState
的值是否為3,就可以利用XHR
對象實現HTTP流。在上述這些瀏覽器中,隨著不斷從服務器接受數據,readyState
的值會周期性的變為3。當readyState
的值變為3時,responseText
屬性中就會保存接收到的所有數據。此時,就需要比較此前接收到的數據,決定從什么位置開始取得最新的數據,使用XHR
對象實現HTTP流的典型代碼如下所示。
function createStreamClient (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;
process(result);
} else if (xhr.readyState == 4) {
finished(xhr.responseText);
}
}
xhr.send(null);
return xhr;
}
var client = createStreamingClient('streanming.php', function (data) {
console.log('received: ' + data);
}, function (data) {
console.log('done');
})
這里的createStreamingClient()
函數接受三個參數:要連接的URL、在接收到數據時調用的函數以及關閉連接時調用的函數。有時當連接關閉時還需要重新建立,所以關注連接什么時候關閉還是很有必要的。
只要readystatechange
事件發生,而且readyState
為3,就對responseText
進行分割以獲得最新數據。這里的received
變量用于記錄已經處理了多少個字符,每次readyState
值為3時都遞增。然后,通過process
回調函數處理傳入的新數據。而當readyState
為4時,則執行finished
回調函數,傳入響應返回的全部內容。
為了簡化Comet,瀏覽器社區又提供了兩個新的接口。
2.4.3 SSE
SSE(Server-Sent Events,服務器發送事件)是圍繞只讀Comet交互推出的新API。SSE API用于創建到服務器的單向連接,服務器通過這個連接可以發送任意數量的數據。服務器響應的MIME類型必須是text / event-stream,而且是瀏覽器中的JS API能解析格式輸出。SSE支持短輪詢、長輪詢和HTTP流,而且能在斷開連接時自動確定合適重新連接。
2.5 Web Sockets
web sockets是一種瀏覽器的API,它的目標是在一個單獨的持久連接上提供全雙工、雙向通信。(同源策略對web sockets不適用)
web sockets原理:在js創建了web socket之后,會有一個HTTP請求發送到瀏覽器以發起連接。取得服務器響應后,建立的連接會使用HTTP升級從HTTP協議交換為web sockt協議。
只有在支持web socket協議的服務器上才能正常工作。