1. 程式人生 > >AJAX及其在JavaScript中的應用

AJAX及其在JavaScript中的應用

1、什麼是AJAX(遠端指令碼程式設計)

  AJAX不是JavaScript的規範,它只是一個哥們“發明”的縮寫:Asynchronous JavaScript and XML,意思就是用JavaScript執行非同步網路請求。AJAX是與伺服器交換資料的技術,它在不過載全部頁面的情況下,實現了對部分網頁的更新

  如果仔細觀察一個Form的提交,你就會發現,一旦使用者點選“Submit”按鈕,表單開始提交,瀏覽器就會重新整理頁面,然後在新頁面裡告訴你操作是成功了還是失敗了。如果不幸由於網路太慢或者其他原因,就會得到一個404頁面。 這就是Web的運作原理:一次HTTP請求對應一個頁面

  如果要讓使用者留在當前頁面中,同時發出新的HTTP請求,就必須用JavaScript傳送這個新請求,接收到資料後,再用JavaScript更新頁面,這樣一來,使用者就感覺自己仍然停留在當前頁面,但是資料卻可以不斷地更新。

  最早大規模使用AJAX的就是Gmail,Gmail的頁面在首次載入後,剩下的所有資料都依賴於AJAX來更新。其他使用AJAX的應用程式案例還有:谷歌地圖、騰訊微博、優酷視訊、人人網等等。

  用JavaScript寫一個完整的AJAX程式碼並不複雜,但是需要注意:AJAX請求是非同步執行的,也就是說,要通過回撥函式獲得響應。AJAX是一種瀏覽器特性,使JavaScript能夠擺脫其客戶端的界限,並且與Web伺服器上的檔案或者伺服器端程式協同工作。傳統上講,JavaScript的主要侷限之一是:它不能與Web伺服器通訊,因為它是一種客戶端技術——JavaScript在瀏覽器內執行

。僅就使用者互動而言,一般來講,Web頁面早期的侷限之一是:把資料從使用者傳送給伺服器或者從伺服器傳送給使用者一般需要載入和顯示新的頁面,這樣並不友好。

  AJAX是JavaScript使用內建物件XMLHttpRequest與Web伺服器通訊並且無需提交表單或載入頁面的能力。IE、FireFox、Chrome以及其他的現代瀏覽器都支援這個物件。

  AJAX是基於現有的Internet標準,並且聯合使用它們:
   - XMLHttpRequest 物件 (非同步的與伺服器交換資料)
   - JavaScript/DOM (資訊顯示/互動)
   - CSS (給資料定義樣式)
   - XML (作為轉換資料的格式)

  AJAX應用程式與瀏覽器和平臺無關的,其工作原理如下圖所示:

AJAX

2、原生的AJAX寫法

  用JavaScript寫一個完整的AJAX程式碼並不複雜,但是需要注意:AJAX請求是非同步執行的,也就是說,要通過回撥函式獲得響應。在現代瀏覽器上寫AJAX主要依靠XMLHttpRequest物件:

'use strict';
function success(text) {
    console.log(text);
}

function fail(code) {
    console.log('Error code: ' + code);
}

var request = new XMLHttpRequest();      // 新建XMLHttpRequest物件
 // 狀態發生變化時,函式被回撥
request.onreadystatechange = function () {  //對ajax物件進行監聽
    if (request.readyState === 4) { //4表示解析完畢
            // 判斷響應結果:
            if (request.status === 200) {
                // 成功,通過responseText拿到響應的文字:
                return success(request.responseText);
            } else {
                // 失敗,根據響應碼判斷失敗原因:
                return fail(request.status);
            }
    } else {
        // HTTP請求還在繼續...
    }
}

// 傳送請求:
request.open('GET', 'http://www.liaoxuefeng.com/api/categories');
request.send();

alert('請求已傳送,請等待響應...');

  在chrome上執行結果如下:

  對於低版本的IE,需要新建一個ActiveXObject物件:

'use strict';
function success(text) {
    console.log(text);
}

function fail(code) {
    console.log('Error code: ' + code);
}

var request = new ActiveXObject('Microsoft.XMLHTTP'); // 新建Microsoft.XMLHTTP物件

request.onreadystatechange = function () { // 狀態發生變化時,函式被回撥
    if (request.readyState === 4) { // 成功完成
        // 判斷響應結果:
        if (request.status === 200) {
            // 成功,通過responseText拿到響應的文字:
            return success(request.responseText);
        } else {
            // 失敗,根據響應碼判斷失敗原因:
            return fail(request.status);
        }
    } else {
        // HTTP請求還在繼續...
    }
}

// 傳送請求:
request.open('GET', 'http://www.liaoxuefeng.com/api/categories');
request.send();

alert('請求已傳送,請等待響應...');

  如果你想把標準寫法和IE寫法混在一起,可以這麼寫:

var request;
if (window.XMLHttpRequest) {
    request = new XMLHttpRequest();
} else {
    request = new ActiveXObject('Microsoft.XMLHTTP');
}

  通過檢測window物件是否有XMLHttpRequest屬性來確定瀏覽器是否支援標準的XMLHttpRequest。注意,不要根據瀏覽器的navigator.userAgent來檢測瀏覽器是否支援某個JavaScript特性,一是因為這個字串本身可以偽造,二是通過IE版本判斷JavaScript特性將非常複雜。

  當建立了XMLHttpRequest物件後,要先設定onreadystatechange的回撥函式。在回撥函式中,通常我們只需通過readyState === 4判斷請求是否完成,如果已完成,再根據status === 200判斷是否是一個成功的響應。

  XMLHttpRequest物件的open()方法有3個引數,第一個引數指定是GET還是POST,第二個引數指定URL地址,第三個引數指定是否使用非同步,預設是true,所以不用寫。注意,千萬不要把第三個引數指定為false,否則瀏覽器將停止響應,直到AJAX請求完成。如果這個請求耗時10秒,那麼10秒內你會發現瀏覽器處於“假死”狀態

  最後呼叫send()方法才真正傳送請求。GET請求不需要引數,POST請求需要把body部分以字串或者FormData物件傳進去。

  預設情況下,JavaScript在傳送AJAX請求時,URL的域名必須和當前頁面完全一致。完全一致的意思是,域名要相同(www.example.com和example.com不同),協議要相同(http和https不同),埠號要相同(預設是:80埠,它和:8080就不同)。有的瀏覽器口子鬆一點,允許埠不同,大多數瀏覽器都會嚴格遵守這個限制。上面程式碼的URL使用的是絕對路徑(更多的時候用相對路徑),如果當前瀏覽器頁面不在“www.liaoxuefeng.com”這個域名下,執行上面程式碼肯定報錯,在Chrome的控制檯裡,還可以看到錯誤資訊,這是因為瀏覽器的同源策略導致的。

  那是不是用JavaScript無法請求外域(就是其他網站)的URL了呢?方法還是有的,此處不贅述JavaScript的跨域請求方法。

3、jQuery的AJAX寫法

$.get(url,[data],[callback],[dataType])

  說明:url為請求地址,data為請求資料的列表(data引數是可選的,也可以將要傳的引數寫在url裡面),callback為請求成功後的回撥函式,該函式接受兩個引數,第一個為伺服器返回的資料,第二個引數為伺服器的狀態,是可選引數。dataType為預期的伺服器返回資料的型別,是可選引數

  呼叫語法如下:

$.get(URL,data,function(data,status,xhr),dataType)

  引數解釋如下:

get引數

  dataType通常省略不寫,那麼伺服器返回資料的格式其實是字串形式,並不是我們想要的json資料格式

$.get("data.php",$("#firstName.val()"),function(data) {
    $("#getResponse").html(data); //返回的data是字串型別
});

$("button").click(function(){
    $.get("demo_test.php",function(data,status){
        alert("Data: " + data + "\nStatus: " + status);
  });
});

$.post(url,[data],[callback],[dataType])

  說明:這個函式跟get()函式引數差不多,多了一個type引數,dataType為預期的伺服器返回的資料型別,可以是html、xml、json等型別,如果我們設定這個引數為:json,那麼返回的格式就是json格式的,如果沒有設定,就和上面$.get()函式返回的格式一樣,都是字串

  呼叫語法如下:

$.post(URL,data,function(data,status,xhr),dataType)

  引數解釋如下:

post引數

  使用$.post()函式的簡單示例如下:

$.post("emp.do?p=getAllEmp",
    {
        id:deptId,
        x:Math.random()
    },
    function(arry) {
                for(var i=0;i<arry.length;i++) {
                     var op = new Option(arry[i].empName,arry[i].empId);
                     document.getElementById("emp").options.add(op);
                 }
         },
         "json"//設定了獲取資料的型別,所以得到的資料格式為json型別的 
 );

$("button").click(function() {
    $.post("demo_test_post.asp",
        {
            name:"Donald Duck",
            city:"Duckburg"
         },
         function(data,status) {
            alert("Data: " + data + "\nStatus: " + status);
    });
});

$.ajax(opitons)

  說明:$.ajax()這個函式功能強大,可以對ajax進行許多精確的控制,需要詳細說明的請參照相關資料。

  options
  型別:Object
  描述:可選引數

  $.ajax()函式的引數較多,下表列出了所有引數的用法。

ajax引數

  AJAX請求的所有選項都是可選的。具體選項的含義通過一個例項程式展示如下:

$.ajax({
    url:'/comm/test1.php',
    type:'POST', //GET
    async:true,    //或false,是否非同步
    data:{
        name:'yang',age:25
    },
    timeout:5000,    //超時時間
    dataType:'json',    //返回的資料格式:json/xml/html/script/jsonp/text
    contentType:'application/x-www-form-urlencoded',//可有可無,傳送資訊至伺服器時內容的編碼型別,預設值適合大多數情況
    beforeSend:function(xhr){
        console.log(xhr)
        console.log('傳送前')
    },
    success:function(data,textStatus,jqXHR){
        console.log(data)
        console.log(textStatus)
        console.log(jqXHR)
    },
    error:function(xhr,textStatus){
        console.log('錯誤')
        console.log(xhr)
        console.log(textStatus)
    },
    complete:function(){   //請求完成後回撥函式,請求成功或失敗之後均呼叫
        console.log('結束')
    }
})

  在眾多的引數中,經常使用的包括有type, url, data, dataType, async, beforeSend(), success(), error().

$.getJSON(url,[data],[callback])

  說明:$.getJSON(url,[data],[callback])函式沒有type引數,返回的是json型別的,不需要轉換。

$.getJSON("dep.do?p=getAllDep",
    {
        x:Math.random()
    },
    function(arry) {
             for(var i = 0;i < arry.length;i++) {
                 var op = new Option(arry[i].deptName,arry[i].deptId);
                 document.getElementById("dep").options.add(op);
             }
 });

$.getJSON("data.php",$("#firstName.val()"),function(jsonData) {  
    $("#getJSONResponse").html(jsonData.id);
});  
//無需設定,直接獲取的資料型別為json,  
//所以呼叫時需要使用jsonData.id方式  

  JSON是一種理想的資料傳輸格式,它能夠很好的融合JavaScript或其他宿主語言,並且可以被JS直接使用。使用JSON相比傳統的通過GET、POST直接傳送”裸體”資料,在結構上更為合理,也更為安全。至於jQuery的getJSON()函式,只是設定了JSON引數的ajax()函式的一個簡化版本。這個函式也是可以跨域使用的,相比get()、post()有一定優勢。另外這個函式可以通過把請求url寫成”myurl?callback=X”這種格式,讓程式執行回撥函式X。