跳到主要內容
黯羽輕揚每天積累一點點

JS 學習筆記 10_Ajax

免費2015-04-13#JS#Ajax

本文主要介紹 Ajax 技術,XHR 物件的用法以及注意事項,還包括同源策略、跨域方法、跨站請求偽造等內容。

##1.Ajax 概述

Asynchronous JavaScript + XML,支援 js 與伺服器通訊。在不 unload 頁面的前提下從伺服器獲取新數據,以實現更好的用戶體驗(與傳統的單擊 - 等待交互不同的體驗)。

IE5 最先提供了支援,在 MSXML 庫中新增了 XHR 物件(XMLHttpRequest),可以通過 new ActiveXObject(str) 的方式創建 XHR 物件,雖然不是很方便,但至少是原生支援。

##2.XHR 物件

XMLHttpRequest,[IE6-] 對 XHR 物件的實現與其它瀏覽器不同,但可以通過物件檢測來創建跨瀏覽器的 XHR 物件,具體代碼如下:

/*獲取 HttpRequest 物件,可以相容各個瀏覽器 包括 IE5.5+*/
function getHttpObject(){
????if(typeof XMLHttpRequest == "undefined"){//如果該物件未定義,則自定義該物件
????????XMLHttpRequest = function(){
????????????try{
????????????????return new ActiveXObject("Msxml2.XMLHTTP.6.0");
????????????}catch(e){}
????????????try{
????????????????return new ActiveXObject("Msxml2.XMLHTTP.3.0");
????????????}catch(e){}
????????????try{
????????????????return new ActiveXObject("Msxml2.XMLHTTP");
????????????}catch(e){}
????????????try{//老版本的 Internet Explorer(IE5 和 IE6)
????????????????return new ActiveXObject("Microsoft.XMLHTTP");
????????????}catch(e){}
?????????????
????????????return false;
????????}
????}
?????
????return new XMLHttpRequest();
}

XHR 物件的屬性如下:

  • responseText:響應體

  • responseXML:如果響應內容是"text/xml"或者"application/xml",這個屬性會保存響應數據的 XML DOM 文檔

  • status:響應的 HTTP 狀態(404,200 之類的)

  • statusText:HTTP 狀態說明,不可靠,因為各個瀏覽器不一樣,直接用 status 狀態碼最可靠

  • readyState:多用於異步請求,雖然同步請求也能用,但沒什麼意義,readyState 的 5 個值如下:

    • 0:未初始化。還沒調用 open 方法

    • 1:啟動。調用了 open 沒調用 send

    • 2:發送。調用了 send 還沒收到響應

    • 3:接收。拿到了部分響應數據

    • 4:完成。拿到了所有數據,並且數據已經可用了

##3.用 XHR 物件實現執行回調函數

var xhr = getHttpObject();
xhr.onreadystatechange = function(){
??if(xhr.readyState === 4){
????if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){//本來只用檢測 200 成功和 304 不變但有些瀏覽器會把 200 錯報成 204
??????//執行 callback
????}
????else{
??????//請求失敗
????}
??}
}

注意:必須在 open 函數之前設置 readystatechange 事件處理器,以保證全瀏覽器相容。

##4.用 XHR 物件實現 get/post 請求

//get 請求
xhr.open('get', url, false/true);//初始化,false/true ~ 同步/異步
xhr.send(null);//發送請求,null 是為了相容性
//post 請求
xhr.open('post', url, false/true);//同上
xhr.send(str);
/* 可以在 open 後 send 前設置請求頭,比如添加 cookie 信息
xhr.setRequestHeader(strHeader, strValue);
*/

注意:伺服器對 post 請求和提交 web 表單的請求處理方式不一致,但可以通過修改 HTTP 頭來模擬表單提交。

但如果要發送表單數據的話,send 的參數 str 必須是經過序列化的表單數據。此時需要模擬實現序列化函數,比較麻煩,JQuery 提供了序列化支援,可以直接$('#mForm').serialize() 序列化表單。

##5.終止請求

xhr.abort();可以在響應返回前終止請求,abort 之後不會再觸發事件,不允許再訪問 xhr 的響應相關屬性。

注意:終止請求後應該解除 XHR 物件的引用,不建議重用 XHR 物件(由於記憶體原因)。

##6.用 post 還是用 get?

post 請求消耗的資源多,而且數據傳輸速率也比 get 請求慢很多。

但 get 請求不安全,而且 IE 對 URI 的長度有限制(不超過 2048 個字節),所以盡量用 get,不行再用 post

##7.CORS 概述

Cross-Origin Resource Sharing,跨源資源共享,Ajax 受同源策略限制,通過一些 CORS 技術可以打破同源策略限制。例如 IE8 的 XDR 物件。

其它瀏覽器通過增強 XHR 物件實現了對 CORS 的原生支援:把 open 函數的 url 參數設置為絕對 URL 就好了。

所以為了消除歧義,應該在訪問本地資源時用相對 URL,訪問遠程資源時用絕對 URL。

##8.其它跨域技術

  1. 圖像 Ping

    var img = new Image();
    img.onload = img.onerror = function(){
      //響應返回,執行回調函數
    }
    img.src = url;//一旦設置了 src 屬性,就會立即請求(加載)圖片,而不是把 img 元素插入 DOM 樹後才開始
    

只能發送 get 請求,且無法訪問伺服器的響應文本,多用於跟蹤用戶點擊頁面或動態廣告曝光次數。

  1. JSONP

JSON with Padding,支援瀏覽器與伺服器進行雙向通信,且能夠直接訪問響應文本,但不易確定請求失敗與否,而且從其它域加載代碼執行,會存在安全問題。

有一篇很不錯的介紹跨域技術的博文

##9.CSRF 攻擊

Cross-Site Request Forgery,跨站請求偽造,向頁面直接插入 Ajax 代碼,不存在同源策略限制,從而偽造請求訪問敏感數據。

防範方法有:

  1. 要求用 SSL 連接訪問資源

  2. 要求每次請求必須附帶上特殊算法計算得到的驗證碼

評論

暫無評論,快來發表你的看法吧

提交評論