JavaScript系列----AJAX機制詳解以及跨域通訊

1.Ajax

1.1.Ajax簡介

  Ajax簡介這一部分咱們主要是談一下ajax的起源,ajax是什麼?由於這些是跟技術無關的。因此,大多細節都是一筆帶過。php

  Ajax的起源?html

  Ajax一詞源於2005年 Jesse James Garrett發表的一篇題爲"Ajax:A new Approach to Web Applications".他在這篇文       章中介紹了一種新技術,用他的話說,就是Ajax :Asynchronous JavaScript +XML的縮寫。前端

  Ajax是什麼?ajax

  這種新技術的主要目的就是爲了使前端網頁可以向服務器請求額外的數據而不須要卸載頁面。自從這種技術出現之後,微軟率先引入XHR對象(ajax可以實現的核心對象),而後其餘瀏覽器相繼實現這種技術。總而言之,ajax就是一種能異步通訊的技術。json

1.2.Ajax的核心對象---XMLHttpRequest

  由於IE5是最早引入這個XHR對象的,當時並無事實上的標準。在IE中有三種不一樣的XHR對象版本:MSXML2.XMLHttp,MSXML2.XMLHttp.3.0MSXML2.XMLHttp.6.0;跨域

根據這三種版本號,在IE中建立一個XHR對象以下:瀏覽器

function createXHR() { //IE7以前的版本經過這種方式  var versions = [
    'MSXML2.XMLHttp',
    'MSXML2.XMLHttp.3.0',
    'MSXML2.XMLHttp.6.0'
  ];
  var xhr = null;
  for (var item in versions) {
    try {
      xhr = new ActiveXObject(item); //若不存在該版本,可能會出錯
      if (xhr) break;
    } catch (e) {
      //通常對這種錯誤不作處理
    }
  }
  return xhr;
}

在IE引入這個對象以後,其餘瀏覽器廠商也相繼跟隨,這時候XHR對象成爲事實上的標準!安全

跨瀏覽器建立XHR對象;服務器

function createXHttpRequest() {
  if (typeof XMLHttpRequest !== 'undefined') { //不要用 if(XMLHttpRequest){}這種形式, return new XMLHttpRequest();              //若是是這種形式在找不到XMLHttpRequest函數的狀況下,會報錯。
} else if (typeof ActiveXObject !== 'undefined') { 
return createXHR(); //用到剛纔咱們建立的函數
}
else { throw new Error('不能建立XMLHttpRequest對象'); } }

 

1.2.XMLHttpRequest的用法

XMLHttpRequest對象的函數有6個:cookie

open("method",url,boolean);
//該方法的三個參數,分別爲----提交方式"get"或者"post"等
                //&& url是相對於執行代碼的當前頁面的路徑(使用絕對路徑是容許的)&&是否異步

send();
//這個方法接收一個參數,這個參數是做爲請求主體發送的數據,
//說明: 若是有參數,請使用post方式提交 使用方式以下,send("user="+username+"&pwd="+password); //若是沒有參數,爲了兼容性考慮,必須在參數中傳入null,即send(null);該方式使用get方式提交

abort();             //取消當前響應,關閉鏈接而且結束任何未決的網絡活動。

                    //這個方法把 XMLHttpRequest 對象重置爲 readyState 爲 0 的狀態,而且取消全部未決                         //的網絡活動。例如,若是請求用了太長時間,並且響應再也不必要的時候,能夠調用這個方法。

 

getResponseHeader()     

                    //返回指定的 HTTP 響應頭部的值。其參數是要返回的 HTTP 響應頭部的名稱。可使用任                         //何大小寫來制定這個頭部名字,和響應頭部的比較是不區分大小寫的。

                    //該方法的返回值是指定的 HTTP 響應頭部的值,若是沒有接收到這個頭部或者 readyStat                          //e 小於 3 則爲空字符串。若是接收到多個有指定名稱的頭部,這個頭部的值被鏈接起來並                          //返回,使用逗號和空格分隔開各個頭部的值。

getAllResponseHeaders()              

                   //把 HTTP 響應頭部做爲未解析的字符串返回。

                   //若是 readyState 小於 3,這個方法返回 null。不然,它返回服務器發送的全部 HTTP 響應的

                   //頭部。頭部做爲單個的字符串返回,一行一個頭部。每行用換行符 "\r\n" 隔開。

                         

setRequestHeader()

                  //向一個打開但未發送的請求設置或添加一個 HTTP 請求。

 

  XMLHttpRequest對象的屬性有5個:

屬性 描述
responseText 做爲響應主題被返回的文本
responseXML 若是相響應的是text/html或者application/xml類型的話,這個屬性將保存着響應的XML文檔
status http的響應狀態碼
statusText http狀態的說明
readyState XMLHttpRequest對象的狀態位 0 1 2 3 4 分別表示5種狀態
timeout 設置超時時間,單位是ms.目前只有IE8+支持---還沒有標準化(不推薦使用)

 

  XMLHttpRequest對象的事件屬性onReadyStateChange:-----全部瀏覽器兼容

  該屬性監聽的是  XMLHttpRequest對象的readyState屬性的變化: 

  readyState的變化分別對應以下狀態:

  0:還沒有初始化。未調用open()以前

  1:啓動。調用open()以後,可是未調用send();

  2:發送。調用send()可是還沒有獲得響應。

  3:正在接收數據。剛接收到響應數據開始到接收完成以前。

  4: 完成。數據接收完成。

 

xhr.onreadystatechange = function () {
  if (xhr.readyState == 4) {
    if (xhr.status >= 200 && xhr.status <== 300 || xhr.status == 304) {
      alert(xhr.responseText);
      //處理接收的數據
    } else {
      //請求失敗,未獲得響應數據
    }
  }
}; //補充說明:註冊事件必須發生在send()之前

 

XMLHttpRequest對象的事件屬性ontimeout -----僅限IE8+,不過最新的主流高版本瀏覽器也已經實現(不推薦使用)

xhr.timeout=1000;//一秒鐘

xhr.ontimeout=functon(){
  //處理代碼
  ......
}

  這種使用方式有個問題須要注意,就是在超時以後,在接收到數據後仍然會觸發onreadystatechange事件,若是在處理onreadychange事件時訪問xhr.status屬性,會出錯。因此咱們在訪問該屬性時須要作一下try{}catch處理。可是,由於這個屬性暫不兼容,全部咱們就不重點講了。

 

XMLHttpRequest對象的事件屬性onload onerror onloadstar onbort onprogress

                                                                                                   -----非IE瀏覽器和IE 10+已實現

       onload在IE8以上能夠實現,大部分事件根據readySate變化都可以實現,以上事件只不過是方便使用而已。

 

  onload和onprogress 這兩種事件分別對應着readyState=4和readyState=3的狀況,使用方式分別以下: 

     xhr.onload= function (event) {
            //event只包含一個屬性 event.target=xhr;使用方式只是在readyState=4時差很少..
        }
     xhr.onprogress=function(event){
         //event除了包含event.target=xhr以外,還包含三種屬性
         //lengthComputale(進度信息是否可用),position(已接受字節數)和totalSize(總字節數).
         
     }

補充:有些事件都可以根據readyState的狀態進行模擬。只有有的瀏覽器進行了方便化處理而已。  

 

3.單向跨域技術 ---CORS

 今天咱們這裏講的是客戶端網頁向不在同一個域的服務器請求數據..客戶端在收到返回的數據時時,用回調函數處理數據。

即:

 1. 客戶端向域外服務器請求數據

 2.服務器獲得響應後向客戶端發送數據。

 3.客戶端根據返回的數據執行回調函數.

 

 我知道不一樣域下的iframe也能夠進行通訊,並且這也是一種跨域通訊技術。可是,這種iframe頁面之間的雙向通訊,咱們在下一個專題裏面講解,今天主要講的是單向通訊。

3.1.CORS跨域請求的原理

在用xhr(XMLHttpRequest)對象或者xdr(XDomainRequest)對象,發送域外請求時,大概的實現原理以下圖:

 3.2.IE中CORS技術的實現

 IE8引入了一個XDR類型,這個類型與XHR基本相似,可是其能實現安全可靠地跨域通訊。

 XHD的特色:

 1.cookie不會隨請求發送,也不會隨響應返回。

 2.只能設置請求頭部中的Content-Type片斷。

 3.不能訪問響應頭部信息。

 4.只是支持get和post請求。

 

 XDR支持onload和onerror事件屬性,且其使用方式和XHR基本一致,不過其open()只接收兩個參數,默認是異步的。

var xdr = new XDomainRequest();
xdr.onload = function () {
  //處理xdr.responseText
}
xdr.onerror = function () {
};
xdr.open('get', '絕對url');
xhr.send(null);

 

 

3.3.跨瀏覽器的CORS技術實現

在標準瀏覽器中XHR對象就已經能夠自動實現跨域請求,可是XHR和XDR的不一樣之處:

1.XHR能夠在設置 withCredentials =true時,瀏覽器會把cookie發送給服務器,服務器此時經過設置頭部Access-Control-Allow-Credentials:true時來響應。若是,服務器不設置這個屬性,則瀏覽器會觸發onerror事件。

2.在回調函數中能夠訪問status和statusText屬性,並且支持同步請求。

 如下是實現跨域請求的代碼:

function createCrosRequest(method, url) {
  var xhr = new XMLHttpRequest(); //IE7+
  if ('withCredentials' in xhr) { //IE8-IE9瀏覽器沒有這個屬性
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != 'undefined') {
    xhr = new XDomainRequest();    //IE
    xhr.open(method, url)
  }
  return xhr;
}
var request=CreateCrosRequest("get","url");
if(request){
request.onload=function(){
//處理request.responseText;
}
request.send(null);
}

4.單向跨域技術 ---JSONP技術

 JSONP技術比較簡單,其主要原理主要是利用script標籤的特性。

 script標籤和image標籤同樣,它們都具備src屬性,並且這個屬性是可跨域的。

 

由於script標籤返回的都是js代碼,且該js代碼會自動執行。因此,若是咱們請求返回的數據也是相似一段js代碼的形式,豈不是就能夠實如今腳本加載完畢後自動執行。

若是咱們的請求,返回的數據是 callback + '(' + json + ')'; 這種形式的數據, 那麼在腳本加載完畢以後也就能自動執行callback()函數了.

4.1.客戶端寫法

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
       <button id="button">請求數據</button>
</body>
<script>
    window.onload=function(){
        var button=document.getElementById("ibutton");
        function callback(data){
            //處理data
        }
        button.onclick=function(){
            var script=document.createElement("script");
            script="http://www.sasd.com/json/?callbak=callback"; 
            document.body.insertBefore(script,document.body.firstChild);//加載腳本
            
        }
        
    }
</script>
</html>

   1.客戶端將回調函數名寫入<Script>腳本的url參數中。

   2.script加載的時候會發送跨域請求。

4.2.服務器端

 1.經過url獲得函數名,命名爲callback

 2.將請求的數據做爲函數的參數格式轉化json格式,命名爲。

 3.將返回結果拼接爲 callback+"("+json+")"; --------返回的就是填充式的數據,這段數據在腳本中會自動執行。

 4.返回數據.

 

 4.3.JSONP技術的缺點

 1.由於是經過url傳參數,因此請求只能是get類型的。

 2.<script>目前只有onload屬性事件,onerror尚未統一化,若是加載腳本出錯,客戶端很可貴到反饋。

 3.所請求數據的站點必須是可信任的,若是返回的數據段中注入的有惡意的代碼,危害較大,且難以發現。

相關文章
相關標籤/搜索