1. 程式人生 > 實用技巧 >高階程式設計(第3版)第二十一章Ajax 與 Comet/筆記

高階程式設計(第3版)第二十一章Ajax 與 Comet/筆記

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安全,通行的做法就是驗證傳送請求者是否有許可權訪問相應的資源。