21 Ajax 與 Comet

本章內(nèi)容

  • 使用 XMLHttpRequest對(duì)象
  • 使用XMLHttpRequest事件
  • 跨域 Ajax 通信的限制

Ajax 技術(shù)的核心是 XMLHttpRequest對(duì)象(簡(jiǎn)稱 XHR)。

21.1 XMLHttpRequest 對(duì)象

var xhr = new XMLHttpRequest();

21.1.1 XHR 的用法

在使用 XHR 對(duì)象時(shí),要調(diào)用的第一個(gè)方法是open(),以啟動(dòng)一個(gè)請(qǐng)求以備發(fā)送,它接受 3 個(gè)參數(shù):要發(fā)送的請(qǐng)求類型,請(qǐng)求的 URL 和表示是否異步發(fā)送請(qǐng)求的布爾值。

xhr.open("get", "example.php", false);

只能向同一個(gè)域中使用相同端口和協(xié)議的 URL 發(fā)送請(qǐng)求。如果 URL 與啟動(dòng)請(qǐng)求的頁面有任何差別,都會(huì)引發(fā)安全錯(cuò)誤。

要發(fā)送特定的請(qǐng)求,必須像下面這樣調(diào)用send()方法:

xhr.open("get", "example.txt", false);
xhr.send(null);

這里的send()方法接收一個(gè)參數(shù),即要作為請(qǐng)求主體發(fā)送的數(shù)據(jù)。如果不需要通過請(qǐng)求主體發(fā)送數(shù)據(jù),則必須傳入null,因?yàn)檫@個(gè)參數(shù)對(duì)有些瀏覽器來說是必需的。調(diào)用send()后,請(qǐng)求就會(huì)被分派到服務(wù)器。
在收到響應(yīng)后,響應(yīng)的數(shù)據(jù)會(huì)自動(dòng)填充 XHR 對(duì)象的屬性,相關(guān)的屬性簡(jiǎn)介如下。

  • responseText:作為響應(yīng)主體被返回的文本
  • responseXML:如果響應(yīng)的內(nèi)容類型是"text/xml""application/xml",這個(gè)屬性中將保存包含著響應(yīng)數(shù)據(jù)的 XML DOM 文檔。
  • status:響應(yīng)的 HTTP 狀態(tài)。
  • statusText:HTTP 狀態(tài)的說明。

為確保接收適當(dāng)?shù)捻憫?yīng),應(yīng)該像下面這樣檢查上述這兩種狀態(tài)代碼:

xhr.open("get", "example.txt", false);
xhr.send(null);
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
  alert(xhr.responseText);
} else {
  alert("request was unsuccessful:" + xhr.status);
}

多數(shù)情況下,需要發(fā)送異步請(qǐng)求,才能讓 JavaScript 繼續(xù)執(zhí)行而不必等待響應(yīng)。此時(shí),可以檢測(cè) XHR 對(duì)象的readyState屬性,該屬性表示請(qǐng)求/響應(yīng)過程的當(dāng)前活動(dòng)階段。這個(gè)屬性可取的值如下。

  • 0:未初始化。尚未調(diào)用open()方法。
  • 1:?jiǎn)?dòng)。已經(jīng)調(diào)用open()方法,但尚未調(diào)用send()方法。
  • 2:發(fā)送。已經(jīng)調(diào)用send()方法,但尚未接收到響應(yīng)。
  • 3:接收。已經(jīng)接收到部分響應(yīng)數(shù)據(jù)。
  • 4:完成。已經(jīng)接收到全部響應(yīng)數(shù)據(jù),而且已經(jīng)可以在客戶端使用了。

readyState屬性值變化時(shí),會(huì)觸發(fā)readystatechange事件
。通常,我們只對(duì)readyState值為 4 的階段感興趣,因?yàn)檫@時(shí)所有數(shù)據(jù)都已經(jīng)就緒。

var xhr = createXHR();
xhr.onreadystatechange = function () {
  if (xhr.readyState == 4) {
    if ((xhr.state >= 200 && xhr.state.status < 300) || xhr.status == 304) {
      alert(xhr.responseText);
    } else {
      alert("request was unsuccessful: " + xhr.status);
    }
  }
};
xhr.open("get", "example.txt", true);
xhr.send(null);

另外,在接收到響應(yīng)之前還可以調(diào)用abort()方法來取消異步請(qǐng)求。

xhr.abort();

21.1.2 HTTP 頭部信息

每個(gè) HTTP 請(qǐng)求和響應(yīng)都會(huì)帶有相應(yīng)的頭部信息,其中有的對(duì)開發(fā)人員有用,有的也沒有什么用。
XHR對(duì)象提供了操作這兩種頭部信息的方法。
默認(rèn)情況下,在發(fā)送XHR請(qǐng)求的同時(shí),還會(huì)發(fā)送下列頭部信息(略)。
使用setRequestHeader()方法可以設(shè)置自定義的請(qǐng)求頭部信息。必須在調(diào)用open()方法之后且調(diào)用send()方法之前調(diào)用setRequestHeader()。
調(diào)用XHR對(duì)象的getResponseHeader()方法并傳入頭部字段名稱,可以取得相應(yīng)的響應(yīng)頭部信息。

21.1.3 GET 請(qǐng)求

查詢字符串中每個(gè)參數(shù)的名稱和值都必須使用encodeURIComponent()進(jìn)行編碼,然后才能放到 URL 的末尾;而且所有名-值對(duì)都必須由和號(hào)分隔。
下面這個(gè)函數(shù)可以輔助向現(xiàn)有 URL 的末尾添加查詢字符串參數(shù):

function addURLParam(url, name, value) {
  url += (url.indexOf("?") == -1 ? "?" : "&");
  url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
  return url;
}

21.2.4 POST 請(qǐng)求

21.2 XMLHttpRequest 2 級(jí)

21.2.1 FormData

21.2.2 超時(shí)設(shè)定

21.2.3 overrideMimeType() 方法

21.3 進(jìn)度事件

21.3.1 load 事件

21.3.2 progress 事件

21.4 跨源資源共享

21.4.1 IE 對(duì) CORS 的實(shí)現(xiàn)

21.4.2 其他瀏覽器對(duì) CORS 的實(shí)現(xiàn)

使用標(biāo)準(zhǔn)的 XHR 對(duì)象并在open()方法中傳入絕對(duì) URL 即可。
跨域 XHR 對(duì)象也有一些限制。

  • 不能使用setRequestHeader()設(shè)置自定義頭部。
  • 不能發(fā)送和接收 cookie。
  • 調(diào)用getAllResponseHeaders()方法總會(huì)返回空字符串。

21.4.3 Preflighted Requests

21.4.4 帶憑據(jù)的請(qǐng)求

21.4.5 跨瀏覽器的 CORS

21.5 其他跨域技術(shù)

21.5.1 圖像 Ping

21.5.2 JSONP

21.5.3 Comet

Comet 是一種更高級(jí)的 Ajax 技術(shù)(“服務(wù)器推送”)。Comet 則是一種服務(wù)器向頁面推送數(shù)據(jù)的技術(shù)。能夠讓信息幾乎實(shí)時(shí)地被推送到頁面上,非常適合處理體育比賽的分?jǐn)?shù)和股票報(bào)價(jià)。
有兩種實(shí)現(xiàn) Comet 的方式:長(zhǎng)輪詢和流。長(zhǎng)輪詢是傳統(tǒng)輪詢的一個(gè)翻版,即瀏覽器定時(shí)向服務(wù)器發(fā)送請(qǐng)求,看有沒有更新的數(shù)據(jù)。
長(zhǎng)輪詢把短輪詢顛倒了一下。頁面發(fā)起一個(gè)服務(wù)器的請(qǐng)求,然后服務(wù)器一直保持連接打開,直到有數(shù)據(jù)可發(fā)送。發(fā)送完數(shù)據(jù)之后,瀏覽器關(guān)閉連接,隨即又發(fā)起一個(gè)到服務(wù)器的新請(qǐng)求。這一過程在頁面打開期間一直持續(xù)不斷。
輪詢的優(yōu)勢(shì)是所有瀏覽器都支持,因?yàn)槭褂?XHR 對(duì)象和setTimeout()就能實(shí)現(xiàn)。而你要做的就是決定什么時(shí)候發(fā)送請(qǐng)求。
第二種是 HTTP 流。它在頁面的整個(gè)生命周期內(nèi)只使用一個(gè) HTTP 連接。具體來說,就是瀏覽器向服務(wù)器發(fā)送一個(gè)請(qǐng)求,就是瀏覽器向服務(wù)器發(fā)送一個(gè)請(qǐng)求,而服務(wù)器保持連接打開,然后周期性地向?yàn)g覽器發(fā)送數(shù)據(jù)。
所有服務(wù)器端語言都支持打印到輸出緩存然后刷新(將輸出緩存中的內(nèi)容一次性全部發(fā)送到客戶端)的功能。而這正是實(shí)現(xiàn) HTTP 流的關(guān)鍵所在。
通過偵聽readystatechange事件及檢測(cè)readyState的值是否為 3,就可以利用 XHR 對(duì)象實(shí)現(xiàn) HTTP 流。

21.5.4 服務(wù)器發(fā)送事件

SSE(Server-Sent Events, 服務(wù)器發(fā)送事件)是圍繞只讀 Comet 交互推出的 API 或者模式。SSE API 用于創(chuàng)建到服務(wù)器的單向連接,服務(wù)器通過這個(gè)連接可以發(fā)送任意數(shù)量的數(shù)據(jù)。

21.5.5 Web Sockets

目標(biāo)是在一個(gè)單獨(dú)的持久連接上提供全雙工、雙向通信。

21.5.6 SSE 與 Web Sockets

21.6 安全

為確保通過 XHR 訪問的 URL 安全,通行的做法就是驗(yàn)證發(fā)送請(qǐng)求者是否有權(quán)限訪問相應(yīng)的資源。
有下列幾種方式可供選擇

  • 要求以 SSL 連接來訪問可以通過 XHR 請(qǐng)求的資源。
  • 要求每一次請(qǐng)求都要附帶經(jīng)過相應(yīng)算法計(jì)算得到的驗(yàn)證碼。

21.7 小結(jié)

Ajax 是無需刷新頁面就能夠從服務(wù)器取得數(shù)據(jù)的一種方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 緒論: AJAX技術(shù)的核心為XHR(XMLHttpRequest)對(duì)象AJAX功能:向服務(wù)器請(qǐng)求額外的數(shù)據(jù)而...
    xiaoguo16閱讀 282評(píng)論 0 1
  • AJAX 原生js操作ajax 1.創(chuàng)建XMLHttpRequest對(duì)象 var xhr = new XMLHtt...
    碧玉含香閱讀 3,574評(píng)論 0 7
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 12,446評(píng)論 6 13
  • Ajax:Asynchronous JavaScript + XML的簡(jiǎn)寫。Ajax技術(shù)的核心是XMLHttpRe...
    exialym閱讀 921評(píng)論 0 8
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,641評(píng)論 19 139

友情鏈接更多精彩內(nèi)容