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在瀏覽器內執行
AJAX是JavaScript使用內建物件XMLHttpRequest與Web伺服器通訊並且無需提交表單或載入頁面的能力。IE、FireFox、Chrome以及其他的現代瀏覽器都支援這個物件。
AJAX是基於現有的Internet標準,並且聯合使用它們:
- XMLHttpRequest 物件 (非同步的與伺服器交換資料)
- JavaScript/DOM (資訊顯示/互動)
- CSS (給資料定義樣式)
- XML (作為轉換資料的格式)
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)
引數解釋如下:
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("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({
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。