在我們平常使用web瀏覽器訪問網站時,大部分都是通過超鏈接或者是form表單對web服務器發送請求。同時,javascript腳本也可以通過修改window.location變量或者調用表單的submit()方法來讓web瀏覽器發送請求。但這種方式的請求會刷新瀏覽器的頁面。接下來我說的技術就是如何在web瀏覽器沒有加載新頁面的情況下發送一個http請求。
Ajax( Asynchronous Javascript and XML)技術,最早出現在2005年2月。這種技術涉及到了js腳本對dom,xml,json等不同文檔類型操作,瞭解http協議狀態的情況等等。
XMLHttpRequest對象,在很多書籍中都會有所講到,實質上相當於瀏覽器開放了一個HTTP的API接口提供給javascript語言進行操作。所有的操作方法和屬性都內置在XMLHttpRequest對象中。如果有一定了解HTTP協議的人,那麼對這門技術掌握六七成了。同時請求方式爲客戶端像服務端主動建立連接,屬於客戶端推送的方式。那麼不多說,我們開始創建一個這樣的對象吧。
1.新建XMLHttpRequest對象
var xhr = new XMLHttpRequest(); //創建一個XMLHttpRequest對象。
這種創建方式適合大多數瀏覽器,如IE7+,FireFox,Chrome,Safari等等。但我們熟知的IE6以前是不支持這種創建方式的,因爲以前的IE瀏覽器是通過加載插件的方式提供這樣的接口。接下來的代碼就是爲了滿足現有主流瀏覽器,創建XMLHttpRequest對象。
function createXHR(){
if( typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
}
if(typeof ActiveXobject == "undefined"){
throw new Error(" not support ");
}
//判斷是否爲 IE6或IE6以下版本
if(typeof arguments.callee.activeString != "string"){
var versions = ["MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp3.0","MSXML2.XMLHttp"],
i,len;
for (var i = 0;i<versions.length;i++) {
try{
//嘗試使用不同版本的插件新建對象
new ActiveXobject(versions[i]);
//將合適的版本保存至 activeString屬性中
//arguments.callee代表的是調用函數,這裏指的是createXHR
arguments.callee.activeString=versions[i];
break;
}catch(ex){
// no action
}
};
}
//返回實例對象
return new ActiveXobject(arguments.callee.activeString);
}
這樣我們就可以通過以下代碼創建具有操作HTTP請求的對象了。
var request = createXHR(); // 函數返回XMLHttpRequest對象
2.建立一個簡單的GET請求
在這裏,我使用了一個簡單的函數,來處理普通的get請求。一般get請求多用於查詢操作,因爲它自帶一定的瀏覽器緩存,以減少對服務器的壓力。
/**
* 發送普通的get請求
* @param {string} url 請求url
* @param {[Object]} data 請求參數
* @param {[Object]} callback 回調函數
*/
function getData(url,data,callback){
var xhr = createXHR(); //新建一個XMLHttpRequest對象
if(arguments.length > 1){
url += "?" + encodeFormData(data);
}
xhr.open("GET",url); //打開一個請求
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && callback){
callback(xhr); //將xhr對象傳入回調函數
}
}
xhr.send(null); //請求發送
}
這裏出現裏一些自定義的函數,以及XMLHttpRequest自帶的事件,屬性和方法.首先我們說下encodeFormData()函數,這是將對象的屬性名和屬性值序列化成HTTP協議的請求參數格式 鍵名1=鍵值1&鍵名2=鍵值2…. 具體的代碼如下:
/**
* [encodeFormData 生成合法的請求參數]
* @param {[Object]} data
* @return {[String]}
*/
function encodeFormData(data){
if(!data){ return ""; } // 返回空字符串
var paris=[],name,value;
for(name in data){
if(!data.hasOwnProperty(name)){ continue; } // 跳過繼承屬性
if(typeof data[name] == "function"){ continue; } //跳過函數類型
name = encodeURIComponent(name.replace('%20','+')); //名稱編碼
value = encodeURIComponent(data[name].replace('%20','+')); //值編碼
paris.push(name+"="+value); //添加到paris數組中
}
return paris.join("&");
}
然後就是xhr.open()方法。這個方法主要有兩個必須的部分,請求方式和URL地址。調用這個方法的目的是爲了生成請求頭部的信息。此時並沒有對服務器進行請求操作。這裏只是簡單的介紹了這個方法。
接下來就是xhr.onreadystatechange 事件。與大多數事件一樣,事件名稱以on開頭。這個事件觸發的條件是xhr.readyState的值發生改變。而xhr.readyState總共有5個狀態值.
1. UNSET 0 open()尚未調用
2. OPENED 1 open()已調用
3. HEADERS_RECEIVED 2 接收到頭信息
4. LOADING 3 接受響應主題
5. DONE 4 響應完成
我們設置了這個觸發後執行的函數後,通過判斷readyState的值來確定響應是否完成。同時響應攜帶的信息都會添加到我們新建的xhr實例中去。響應完成後就會執行回調函數。
接下里我們只要使用getData()方法,然後處理獲取到服務端的信息。
var url = "http://localhost:8080/home/user/isRegister"; //確保爲同服務器的地址,跨域的情況暫時無法處理 主要來驗證用戶名是否存在
var data ={ username : "liyanlong1993" }; // 字面量對象
getData(url,data,checkRegister); //調用Ajax請求
function checkRegister(res){
//獲取響應頭部類型
var type = res.getResponseHeader("Content-Type"),
data;
if(type === "application/json"){ //服務器返回的響應頭數據格式爲json類型
data = JSON.parse(res.responseText);
}else{
alert('請求錯誤');
console.log('error request');
return ;
}
if(data.result === undefined){
console.log('返回格式不正確');
return ;
}
if(data.result){
console.log('用戶已註冊');
}else{
console.log('用戶尚未註冊');
}
}
Ajax請求並非如只可以請求獲取XML格式的數據,該例子則是獲取JSON格式的數據。實際上得到的是文本數據,服務器端傳遞過來的響應頭部信息爲”application/json”。然後通過JSON.parse()方法進行轉換。服務端發送的響應的主體如下截圖所示:
確實是一個可以轉換成JSON數據的文本字符串。
3.小結
整個過程,瞭解之後其實並不複雜。但Ajax所能做到的並不只是這些,接下來會介紹一些難度有所上升的知識。謝謝大家能看到這裏。