高階程式設計(第3版)第二十一章Ajax 與 Comet/筆記
阿新 • • 發佈:2020-07-27
Ajax 與 Comet
Ajax技術的核心是 XMLHttpRequest 物件(簡稱 XHR)。能夠以非同步方式從伺服器取得更多資訊,意味著使用者單擊後,可以不必重新整理頁面也能取得新資料。 也就是說,可以使用 XHR 物件取得新資料,然後再通過 DOM 將新資料插入到頁面中。
XMLHttpRequest 物件
var xhr = new XMLHttpRequest();
- XHR的用法
- 在使用 XHR 物件時,要呼叫的第一個方法是 open()方法
- 它接受 3 個引數:
- 要傳送的請求的型別 ("get"、"post"等)
- 請求的 URL
- 表示是否非同步傳送請求的布林值。(false是同步)
xhr.open("get", "example.php", false);
這行程式碼會啟動一個針對 example.php 的 GET 請求。
有關這行程式碼,需要說明兩點:
一是 URL 相對於執行程式碼的當前頁面(當然也可以使用絕對路徑);
二是呼叫 open()方法並不會真正傳送請求, 而只是啟動一個請求以備傳送。
- 要傳送特定的請求,必須呼叫 send()方法
- 接收一個引數,即要作為請求主體傳送的資料。
- 如果不需要通過請求主體傳送 資料,則必須傳入 null
- 在收到響應後,響應 的資料會自動填充 XHR物件的屬性,相關的屬性簡介如下。
status:響應的 HTTP狀態。
statusText:HTTP狀態的說明。
responseText:作為響應主體被返回的文字。
responseXML:如果響應的內容型別是"text/xml"或"application/xml",
這個屬性中將儲存包含著響應資料的 XML DOM文件。
- 在接收到響應後,第一步是檢查 status 屬性,以確定響應已經成功返回。
- 可以檢測 XHR物件的 readyState 屬性,該屬性表示請求 /響應過程的當前活動階段。
0:未初始化。尚未呼叫 open()方法。
1:啟動。已經呼叫 open()方法,但尚未呼叫 send()方法。
2:傳送。已經呼叫 send()方法,但尚未接收到響應。
3:接收。已經接收到部分響應資料。
4:完成。已經接收到全部響應資料,而且已經可以在客戶端使用了。
- 只要 readyState 屬性的值由一個值變成另一個值,都會觸發一次 readystatechange 事件
- 另外,在接收到響應之前還可以呼叫 abort()方法來取消非同步請求,如xhr.abort();
- HTTP頭部資訊
- 預設情況下,在傳送 XHR 請求的同時,還會發送下列頭部資訊。
- 使用 setRequestHeader()方法可以設定自定義的請求頭部資訊。
- 這個方法接受兩個引數:
- 頭部欄位的名稱
- 頭部欄位的值。
- 要成功傳送請求頭部資訊,必須在呼叫 open()方法之後且呼叫 send()方法 之前呼叫這個方法
- 在沒有自定義資訊的情況 下,getAllResponseHeaders()方法通常會返回如下所示的多行文字內容
Date: Sun, 14 Nov 2004 18:04:03 GMT
Server: Apache/1.3.29 (Unix)
Vary: Accept
X-Powered-By: PHP/4.3.8
Connection: close
Content-Type: text/html; charset=iso-8859-1
//這種格式化的輸出可以方便我們檢查響應中所有頭部欄位的名稱,而不必一個一個地檢查某個欄位 是否存在。
- GET請求
查詢字串中每個引數的名 稱和值都必須使用 encodeURIComponent()進行編碼,然後才能放到 URL 的末尾;
而且所有名-值對兒都必須由和號(&)分隔
- POST請求
- 通常用於向伺服器傳送應該被儲存的資料
xhr.open("post", "postexample.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById("user-info");
xhr.send(serialize(form));
XMLHttpRequest 2級
- FormData
- FormData 為序列化表單以及建立與表單格式相同的資料(用於通過 XHR傳輸)提供 了便利
//建立一個 FormData 物件
var data = new FormData();
data.append("name", "Nicholas");
//建立FormData 的例項
var data = new FormData(document.forms[0]);
//以將它直接傳給 XHR的 send()方法
xhr.open("post","postexample.php", true);
var form = document.getElementById("user-info");
xhr.send(new FormData(form));
//使用 FormData 的方便之處體現在不必明確地在 XHR 物件上設定請求頭部
- 超時設定
- timeout 屬性,表示請求在等待響應多少毫秒之後就終止。
- 在給 timeout 設定一個數值後,如果在規定的時間內瀏覽器還沒有接收到響應
- 那麼就會觸發 timeout 事 件,進而會呼叫 ontimeout 事件處理程式。
xhr.open("get", "timeout.php", true);
xhr.timeout = 1000; //將超時設定為 1 秒鐘(僅適用於 IE8+)
xhr.ontimeout = function(){
alert("Request did not return in a second.");
};
xhr.send(null);
- overrideMimeType()方法
- 用於重寫 XHR響應的 MIME 型別
- 返回響應的 MIME型別決定了 XHR物件如何處理它
- 呼叫 overrideMimeType()必須在 send()方法之前,才能保證重寫響應的 MIME型別
進度事件
- load事件
- 只要瀏覽器接收到伺服器的響應,不管其狀態如何,都會觸發 load 事件
- progress事件
- 在瀏覽器接收新資料期間週期性地觸發
- 必須在呼叫 open()方法之前新增 onprogress 事件處理程式
跨源資源共享
- IE對CORS的實現
- 其他瀏覽器對CORS的實現
- Preflighted Requests
- 帶憑據的請求
- 跨瀏覽器的CORS
其他跨域技術
- 影象Ping
- 影象 Ping 是與伺服器進行簡單、單向的跨域通訊的一種方式。
- 請求的資料是通過查詢字串形式傳送的,而響應可以是任意內容,但通常是畫素圖或 204響應。
- 影象 Ping常用於跟蹤使用者點選頁面或動態廣告曝光次數。
- 影象 Ping有兩個主要的缺點,一是隻 能傳送 GET 請求,二是無法訪問伺服器的響應文字。
var img = new Image();
img.onload = img.onerror = function(){
alert("Done!");
};
img.src = "http://www.example.com/test?name=Nicholas";
- JSONP
- JSONP由兩部分組成:回撥函式和資料。
- 與影象 Ping 相比,它的優點 在於能夠直接訪問響應文字,支援在瀏覽器與伺服器之間雙向通訊。
- 不過,JSONP也有兩點不足。
- 首先,JSONP是從其他域中載入程式碼執行。
- 其次,要確定 JSONP請求是否失敗並不容易。
- JSONP 是通過動態<script>元素來使用的,使用時可以為 src 屬性指定一個跨域 URL
function handleResponse(response){
alert("You’re at IP address " + response.ip + ", which is in " +
response.city + ", " + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
- Comet
- Comet 是對 Ajax 的進一步擴充套件,讓伺服器幾乎能夠實時地向客戶端推送資料。
- 實現 Comet 的手段 主要有兩個:長輪詢和 HTTP流。
- 所有瀏覽器都支援長輪詢,而只有部分瀏覽器原生支援 HTTP流。
- SSE (伺服器傳送事件)是一種實現 Comet 互動的瀏覽器 API,既支援長輪詢,也支援 HTTP流。
- 伺服器傳送事件
- Web Sockets
- Web Sockets是一種與伺服器進行全雙工、雙向通訊的通道。
- 與其他方案不同,Web Sockets不使用 HTTP 協議,而使用一種自定義的協議。
- 這種協議專門為快速傳輸小資料設計。雖然要求使用不同的 Web 伺服器,但卻具有速度上的優勢。
- SSE與Web Sockets
安全
為確保通過 XHR訪問的 URL安全,通行的做法就是驗證傳送請求者是否有許可權訪問相應的資源。