js中Ajax知識詳解


一.XMLHttpRequest

Ajax技術核心是XMLHttpRequest對象(簡稱XHR),這是由微軟首先引入的一個特性,其他瀏覽器提供商后來都提供了相同的實現。在XHR出現之前,Ajax式的通信必須借助一些hack手段來實現,大多數是使用隱藏的框架或內嵌框架。

XHR的出現,提供了向服務器發送請求和解析服務器響應提供了流暢的接口。能夠以異步方式從服務器獲取更多的信息,這就意味着,用戶只要觸發某一事件,在不刷新網頁的情況下,更新服務器最新的數據。

雖然Ajax中的x代表的是XML,但Ajax通信和數據格式無關,也就是說這種技術不一定使用XML

 

IE7+FirefoxOperaChromeSafari都支持原生的XHR對象,在這些瀏覽器中創建XHR對象可以直接實例化XMLHttpRequest即可。

var xhr = new XMLHttpRequest();

alert(xhr); //XMLHttpRequest

 

如果是IE6及以下,那么我們必須還需要使用ActiveX對象通過MSXML庫來實現。在低版本IE瀏覽器可能會遇到三種不同版本的XHR對象,即MSXML2.XMLHttpMSXML2.XMLHttp.3.0MSXML2.XMLHttp.6.0。我們可以編寫一個函數。

function createXHR() {

if (typeof XMLHttpRequest != 'undefined') {

return new XMLHttpRequest();

} else if  (typeof ActiveXObject != 'undefined') {

var versions = [

'MSXML2.XMLHttp.6.0',

'MSXML2.XMLHttp.3.0',

'MSXML2.XMLHttp'

];

for (var i = 0; i < versions.length; i ++) {

try {

return new ActiveXObject(version[i]);

} catch (e) {

//跳過

}

}

} else {

throw new Error('您的瀏覽器不支持XHR對象!');

}

}

 

var xhr = new createXHR();

 

在使用XHR對象時,先必須調用open()方法,它接受三個參數:要發送的請求類型(getpost)、請求的URL和表示是否異步。

xhr.open('get', 'demo.php', false); //對於demo.phpget請求,false同步

 

PSdemo.php的代碼如下:

<?php echo Date('Y-m-d H:i:s')?> //一個時間

 

open()方法並不會真正發送請求,而只是啟動一個請求以備發送。通過send()方法進行發送請求,send()方法接受一個參數,作為請求主體發送的數據。如果不需要則,必須填null。執行send()方法之后,請求就會發送到服務器上。

xhr.send(null); //發送請求

 

當請求發送到服務器端,收到響應后,響應的數據會自動填充XHR對象的屬性。那么一共有四個屬性:

 

屬性名

說明

responseText

作為響應主體被返回的文本

responseXML

如果響應主體內容類型是"text/xml""application/xml",則返回包含響應數據的XML DOM文檔

status

響應的HTTP狀態

statusText

HTTP狀態的說明

 

接受響應之后,第一步檢查status屬性,以確定響應已經成功返回。一般而已HTTP狀態代碼為200作為成功的標志。除了成功的狀態代碼,還有一些別的:

 

 

HTTP狀態碼

狀態字符串

說明

200

OK

服務器成功返回了頁面

400

Bad Request

語法錯誤導致服務器不識別

401

Unauthorized

請求需要用戶認證

404

Not found

指定的URL在服務器上找不到

500

Internal Server Error

服務器遇到意外錯誤,無法完成請求

503

ServiceUnavailable

由於服務器過載或維護導致無法完成請求

 

我們判斷HTTP狀態值即可,不建議使用HTTP狀態說明,因為在跨瀏覽器的時候,可能會不太一致。

addEvent(document, 'click', function () {

var xhr = new createXHR();

xhr.open('get', 'demo.php?rand=' + Math.random(), false); //設置了同步

xhr.send(null);

if (xhr.status == 200) { //如果返回成功了

alert(xhr.responseText); //調出服務器返回的數據

} else {

alert('數據返回失敗!狀態代碼:' + xhr.status + '狀態信息:' + xhr.statusText);

}

});

 

以上的代碼每次點擊頁面的時候,返回的時間都是時時的,不同的,說明都是通過服務器及時加載回的數據。那么我們也可以測試一下在非Ajax情況下的情況,創建一個demo2.php文件,使用非Ajax

<script type="text/javascript" src="base.js"></script>

<script type="text/javascript">

addEvent(document, 'click', function () {

alert("<?php echo Date('Y-m-d H:i:s')?>");

});

</script>

 

同步調用固然簡單,但使用異步調用才是我們真正常用的手段。使用異步調用的時候,需要觸發readystatechange事件,然后檢測readyState屬性即可。這個屬性有五個值:

狀態

說明

0

未初始化

尚未調用open()方法

1

啟動

已經調用open()方法,但尚未調用send()方法

2

發送

已經調用send()方法,但尚未接受響應

3

接受

已經接受到部分響應數據

4

完成

已經接受到全部響應數據,而且可以使用

 

addEvent(document, 'click', function () {

var xhr = new createXHR();

xhr.onreadystatechange = function () {

if (xhr.readyState == 4) {

if (xhr.status == 200) {

alert(xhr.responseText);

} else {

alert('數據返回失敗!狀態代碼:' + xhr.status + '狀態信息:'

+ xhr.statusText);

}

}

};

xhr.open('get', 'demo.php?rand=' + Math.random(), true);

xhr.send(null);

});

 

PS:使用abort()方法可以取消異步請求,放在send()方法之前會報錯。放在responseText之前會得到一個空值。

 

二.GETPOST

在提供服務器請求的過程中,有兩種方式,分別是:GETPOST。在Ajax使用的過程中,GET的使用頻率要比POST高。

在了解這兩種請求方式前,我們先了解一下HTTP頭部信息,包含服務器返回的響應頭信息和客戶端發送出去的請求頭信息。我們可以獲取響應頭信息或者設置請求頭信息。我們可以在Firefox瀏覽器的firebug查看這些信息。

//使用getResponseHeader()獲取單個響應頭信息

alert(xhr.getResponseHeader('Content-Type'));

 

//使用getAllResponseHeaders()獲取整個響應頭信息

alert(xhr.getAllResponseHeaders());

 

//使用setRequestHeader()設置單個請求頭信息

xhr.setRequestHeader('MyHeader', 'Lee'); //放在open方法之后,send方法之前

 

PS:我們只可以獲取服務器返回回來響應頭信息,無法獲取向服務器提交的請求頭信息,自然自定義的請求頭,在JavaScript端是無法獲取到的。

 

GET請求

GET請求是最常見的請求類型,最常用於向服務器查詢某些信息。必要時,可以將查詢字符串參數追加到URL的末尾,以便提交給服務器。

xhr.open('get', 'demo.php?rand=' + Math.random() + '&name=Koo', true);

 

通過URL后的問號給服務器傳遞鍵值對數據,服務器接收到返回響應數據。特殊字符傳參產生的問題可以使用encodeURIComponent()進行編碼處理,中文字符的返回及傳參,可以講頁面保存和設置為utf-8格式即可。

//一個通用的URL提交函數

function addURLParam(url, name, value) {

url += (url.indexOf('?') == -1 ? '?' : '&'); //判斷的url是否有已有參數

url += encodeURIComponent(name) + '=' + encodeURIComponent(value);

alert(url);

return url;

}

 

PS:當沒有encodeURIComponent()方法時,在一些特殊字符比如“&”,會出現錯誤導致無法獲取。

 

POST請求

POST請求可以包含非常多的數據,我們在使用表單提交的時候,很多就是使用的POST傳輸方式。

xhr.open('post', 'demo.php', true);

 

而發送POST請求的數據,不會跟在URL的尾巴上,而是通過send()方法向服務器提交數據。

xhr.send('name=Lee&age=100');

 

一般來說,向服務器發送POST請求由於解析機制的原因,需要進行特別的處理。因為POST請求和Web表單提交是不同的,需要使用XHR來模仿表單提交。

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

 

PS:從性能上來講POST請求比GET請求消耗更多一些,用相同數據比較,GET最多比POST快兩倍。

 

上一節課的JSON也可以使用Ajax來回調訪問。

var url = 'demo.json?rand=' + Math.random();

var box = JSON.parse(xhr.responseText);

 

三.封裝Ajax

因為Ajax使用起來比較麻煩,主要就是參數問題,比如到底使用GET還是POST;到底是使用同步還是異步等等,我們需要封裝一個Ajax函數,來方便我們調用。

function ajax(obj) {

var xhr = new createXHR();

obj.url = obj.url + '?rand=' + Math.random();

obj.data = params(obj.data);

if (obj.method === 'get') obj.url = obj.url.indexOf('?') == -1 ?

obj.url + '?' + obj.data : obj.url + '&' + obj.data;

if (obj.async === true) {

xhr.onreadystatechange = function () {

if (xhr.readyState == 4) callback();

};

}

xhr.open(obj.method, obj.url, obj.async);

if (obj.method === 'post') {

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

xhr.send(obj.data);

} else {

xhr.send(null);

}

if (obj.async === false) {

callback();

}

function callback () {

if (xhr.status == 200) {

 obj.success(xhr.responseText); //回調

} else {

alert('數據返回失敗!狀態代碼:' + xhr.status + '

狀態信息:' + xhr.statusText);

}

}

}

 

//調用ajax

addEvent(document, 'click', function () { //IE6需要重寫addEvent

ajax({

method : 'get',

url : 'demo.php',

data : {

'name' : 'Lee',

'age' : 100

},

success : function (text) {

alert(text);

},

async : true

});

});

 

//名值對編碼

function params(data) {

var arr = [];

for (var i in data) {

arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));

}

return arr.join('&');

}

 

PS:封裝Ajax並不是一開始就形成以上的形態,需要經過多次變化而成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM