接上文AJAX實(shí)現(xiàn)跨域的幾種方法(一)
這一篇是關(guān)于Comet和Web Sockets的筆記伞梯。
2.4 Comet
Ajax是一種從頁(yè)面向服務(wù)器請(qǐng)求數(shù)據(jù)的技術(shù)抱冷,而Comet則是一種服務(wù)器向頁(yè)面推送數(shù)據(jù)的技術(shù)。
Comet能夠讓信息近乎實(shí)時(shí)的被推送到頁(yè)面上袜腥,非常適合處理體育比賽的分?jǐn)?shù)和股票報(bào)價(jià)漆腌。
有兩種實(shí)現(xiàn)Comet的方式:長(zhǎng)輪詢和流畔派。
2.4.1 長(zhǎng)輪詢
長(zhǎng)輪詢是短輪詢(瀏覽器定時(shí)向服務(wù)器發(fā)送請(qǐng)求槐沼,看有沒有更新的數(shù)據(jù))的一個(gè)翻版曙蒸。
所謂長(zhǎng)輪詢指的是
頁(yè)面發(fā)起一個(gè)到服務(wù)器的請(qǐng)求捌治,然后服務(wù)器一直保持連接打開,直到有數(shù)據(jù)可發(fā)送逸爵。發(fā)送完數(shù)據(jù)后具滴,瀏覽器關(guān)閉連接,隨即又發(fā)送一個(gè)到服務(wù)器的新請(qǐng)求师倔。這一過程在頁(yè)面打開期間一直持續(xù)不斷。
無論是短輪詢還是長(zhǎng)輪詢周蹭,瀏覽器都要在接收數(shù)據(jù)之前趋艘,先發(fā)起對(duì)服務(wù)器的連接。兩者最大的區(qū)別在于服務(wù)器如何發(fā)送數(shù)據(jù)凶朗。
- 短輪詢是服務(wù)器立即發(fā)送響應(yīng)瓷胧,無論數(shù)據(jù)是否有效。
- 長(zhǎng)輪詢時(shí)等待發(fā)送響應(yīng)棚愤。
輪詢的優(yōu)勢(shì)是所有瀏覽器都支持搓萧,因?yàn)槭褂?code>XHR對(duì)象和setTimeOut()
就能實(shí)現(xiàn)。而程序員要做的就是決定什么時(shí)候發(fā)送請(qǐng)求宛畦。
2.4.2 HTTP流
流不同于上述兩種輪詢瘸洛,因?yàn)樗陧?yè)面的整個(gè)生命周期內(nèi)只用一個(gè)HTTP連接。具體來說次和,就是瀏覽器向服務(wù)器發(fā)送一個(gè)請(qǐng)求反肋,而服務(wù)器保持連接打開,然后周期性的向?yàn)g覽器發(fā)送數(shù)據(jù)踏施。
所有服務(wù)器端語言都支持打印到輸出緩存然后刷新(將輸出緩存中的內(nèi)容一次性全部發(fā)送到客戶端)的功能石蔗,而這正是實(shí)現(xiàn)HTTP流的關(guān)鍵所在。
在FireFox畅形、Safari养距、Opera和Chrome中,通過偵聽readystatechange
事件及檢測(cè)readyState
的值是否為3日熬,就可以利用XHR
對(duì)象實(shí)現(xiàn)HTTP流棍厌。在上述這些瀏覽器中,隨著不斷從服務(wù)器接受數(shù)據(jù)碍遍,readyState
的值會(huì)周期性的變?yōu)?定铜。當(dāng)readyState
的值變?yōu)?時(shí),responseText
屬性中就會(huì)保存接收到的所有數(shù)據(jù)怕敬。此時(shí)揣炕,就需要比較此前接收到的數(shù)據(jù),決定從什么位置開始取得最新的數(shù)據(jù)东跪,使用XHR
對(duì)象實(shí)現(xiàn)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) {
// 只取得最新數(shù)據(jù)并調(diào)整計(jì)數(shù)器
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()
函數(shù)接受三個(gè)參數(shù):要連接的URL鹰溜、在接收到數(shù)據(jù)時(shí)調(diào)用的函數(shù)以及關(guān)閉連接時(shí)調(diào)用的函數(shù)。有時(shí)當(dāng)連接關(guān)閉時(shí)還需要重新建立丁恭,所以關(guān)注連接什么時(shí)候關(guān)閉還是很有必要的曹动。
只要readystatechange
事件發(fā)生,而且readyState
為3牲览,就對(duì)responseText
進(jìn)行分割以獲得最新數(shù)據(jù)墓陈。這里的received
變量用于記錄已經(jīng)處理了多少個(gè)字符,每次readyState
值為3時(shí)都遞增第献。然后贡必,通過process
回調(diào)函數(shù)處理傳入的新數(shù)據(jù)。而當(dāng)readyState
為4時(shí)庸毫,則執(zhí)行finished
回調(diào)函數(shù)仔拟,傳入響應(yīng)返回的全部?jī)?nèi)容。
為了簡(jiǎn)化Comet飒赃,瀏覽器社區(qū)又提供了兩個(gè)新的接口利花。
2.4.3 SSE
SSE(Server-Sent Events,服務(wù)器發(fā)送事件)是圍繞只讀Comet交互推出的新API载佳。SSE API用于創(chuàng)建到服務(wù)器的單向連接炒事,服務(wù)器通過這個(gè)連接可以發(fā)送任意數(shù)量的數(shù)據(jù)。服務(wù)器響應(yīng)的MIME類型必須是text / event-stream刚盈,而且是瀏覽器中的JS API能解析格式輸出羡洛。SSE支持短輪詢、長(zhǎng)輪詢和HTTP流藕漱,而且能在斷開連接時(shí)自動(dòng)確定合適重新連接欲侮。
2.5 Web Sockets
web sockets是一種瀏覽器的API,它的目標(biāo)是在一個(gè)單獨(dú)的持久連接上提供全雙工肋联、雙向通信威蕉。(同源策略對(duì)web sockets不適用)
web sockets原理:在js創(chuàng)建了web socket之后,會(huì)有一個(gè)HTTP請(qǐng)求發(fā)送到瀏覽器以發(fā)起連接橄仍。取得服務(wù)器響應(yīng)后韧涨,建立的連接會(huì)使用HTTP升級(jí)從HTTP協(xié)議交換為web sockt協(xié)議。
只有在支持web socket協(xié)議的服務(wù)器上才能正常工作侮繁。