1. 程式人生 > >ajax(Asynchronous JavaScript + XML) 技術學習

ajax(Asynchronous JavaScript + XML) 技術學習

域名 asc nco 通過 zed 你會 echo 服務器端 main

參考文檔:https://developer.mozilla.org/en-US/docs/AJAX 本文進行了大致翻譯。 Ajax 本身本不是一門技術,而是在2005年由Jesse James Garrett首創的描述為一個“新”途徑來應用許多已存在的技術,包括:HTML 或者 XHTML, Cascading Style Sheets, JavaScript, The Document Object Model, XML, XSLT, 和最重要的 XMLHttpRequest object。 當把這些技術結合到ajax模型裏的時候,web app可以快速地,逐漸地更新用戶界面來取代以前的刷新整個瀏覽界面,這使得應用更快和用戶使用體驗更好。 盡管x在ajax裏面代表xml,json由於其更輕和是javascript的一部分等優點而被更多的使用。ajax模型裏面的json和xml都是用來包裝數據信息的。

什麽是AJAX?

AJAX 代表 Asynchronous JavaScript And XML. 簡而言之, 他是用 XMLHttpRequestobject 來和服務器交流的方式. 它可以以不同的方式發送和接收信息, 包括 JSON, XML, HTML, 和text文件. AJAX最有吸引力的特性是 "異步", 這意味著它可以在不刷新頁面的情況下同服務器交流,交換數據更新頁面。 ajax的主要兩個主要特性:
  • 不刷新頁面請求數據
  • 從服務器獲取數據

Step 1 – 如何請求

為了用javascript請求服務器,我們要實例化一個有必要功能的對象。這是XMLHttpRequest的來源。起初Internet Explorer實現了一個被稱為XMLHTTP的ActiveX對象。 之後,Mozilla, Safari,和其他瀏覽器廠商陸續實現了XMLHttpRequest對象來支持這個方法和類似於Microsof的ActiveX對象功能。同時,Microsoft也實現了XMLHttpRequest。 // Old compatibility code, no longer needed. if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ... httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 6 and older httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } 註意:以上代碼只做解釋作用,只是創建了XMLHttp的實例。可以跳到step 3去看更實用的例子。 請求之後,我們需要接收請求結果。在這個階段,我們需要告訴XMLHttp請求對象來處理響應的JavaScript方法,通過配置他的onreadystatechangeproperty方法,如下:
httpRequest.onreadystatechange = nameOfTheFunction;
或者
httpRequest.onreadystatechange = function(){
// Process the server response here.
};
在聲明怎麽接受響應之後,我們需要發起請求,通過調用HTTP請求對象的 open() 和 send() 方法,如下:
httpRequest.open(‘GET‘, ‘http://www.example.org/some.file‘, true);
httpRequest.send();
  • open() 的第一個參數是HTTP 請求的方法 – GET, POST, HEAD, 或者其他服務器支持的方法。方法名全部大寫是http標準,不然有些瀏覽器(例如:Firefox)可能會不發器請求。 點擊 W3C specs 獲得更多關於http請求方法的信息。
  • 第二個參數是要請求的url。從安全方面考慮,默認不能跨域請求url。確保所有頁面在同一個域名下,不然調用open()方法,你會得到 "permission denied” 錯誤。 一個常見的跨域是你網站的域名是 domain.tld,但是嘗試用 www.domain.tld訪問頁面。如果真的想跨域請求,查看 HTTP access control。
  • 可選的第三個參數設置這個請求是同步還是異步的。如果是true (默認值), JavaScript 會繼續執行,用戶操作頁面的同時,服務器返回數據。這是 AJAX的A。
send()方法的參數可以是你想發送到服務器的任意數據(POST)。表單數據必須是服務器能解析的形式,例如查詢字符串:
"name=value&anothername="+encodeURIComponent(myVar)+"&so=on"
或者其他形式,例如 multipart/form-data,JSON, XML, 等等。 註意如果你想POST數據,你可能要設置請求的MIME type。例如我們把下面代碼放在調用send()之前,來把表單數據當查詢數據發送:
httpRequest.setRequestHeader(‘Content-Type‘, ‘application/x-www-form-urlencoded‘);

Step 2 – 處理服務器響應

請求的時候,我們已經提供了處理響應的JavaScript方法:
httpRequest.onreadystatechange = nameOfTheFunction;
這個方法做什麽?首先,我們需要檢查請求狀態。如果張臺值為XMLHttpRequest.DONE (4),意味著已經接受了所有服務器的響。
if (httpRequest.readyState === XMLHttpRequest.DONE) {
// Everything is good, the response was received.
} else {
// Not ready yet.
}
readyState 全部可能的值,可以在 XMLHTTPRequest.readyState 查看,如下:
  • 0 (uninitialized) or (請求未初始化)
  • 1 (loading) or (服務器建立連接)
  • 2 (loaded) or (請求被接收)
  • 3 (interactive) or (執行請求)
  • 4 (complete) or (request finished and response is ready請求完成響應到位)
  • Value State Description
    0 UNSENT Client has been created. open() not called yet.
    1 OPENED open() has been called.
    2 HEADERS_RECEIVED send() has been called, and headers and status are available.
    3 LOADING Downloading; responseText holds partial data.
    4 DONE The operation is complete.
(Source) 接下來,檢查HTTP響應的 response code 。查看 W3C看到可能的值。下面例子我們用response code是不是等於200來判斷ajax請求是否成功。
if (httpRequest.status === 200) {
// Perfect!
} else {
// There was a problem with the request.
// For example, the response may have a 404 (Not Found)
// or 500 (Internal Server Error) response code.
}
檢查完響應值後。我們可以隨意處理服務器返回的數據,有兩個選擇獲得這些數據:
  • httpRequest.responseText – 返回服務器響應字符串
  • httpRequest.responseXML – 返回服務器響應XMLDocument 對象 可以傳遞給JavaScript DOM 方法
上面的代碼只有在異步的情況下有效(open() 的第三個參數設置為true)。如果你用同步請求,就沒必要指定一個方法。但是我們不鼓勵使用同步請求,因為同步會導致極差的用戶體驗。

Step 3 – 一個簡單的例子

我們把上面的放在一起合成一個簡單的HTTP請求。我們的JavaScript 將請求一個HTML 文檔, test.html, 包含一個字符串 "I‘m a test."然後我們alert()響應內容。這個例子使用普通的JavaScript — 沒有引入jQuery, HTML, XML 和 PHP 文件應該放在同一級目錄下。
<button id="ajaxButton" type="button">Make a request</button>

<script>
(function() {
var httpRequest;
document.getElementById("ajaxButton").addEventListener(‘click‘, makeRequest);

function makeRequest() {
httpRequest = new XMLHttpRequest();

if (!httpRequest) {
alert(‘Giving up :( Cannot create an XMLHTTP instance‘);
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open(‘GET‘, ‘test.html‘);
httpRequest.send();
}

function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert(‘There was a problem with the request.‘);
}
}
}
})();
</script>
在這個例子裏:
  • 用戶點擊"Make a request” 按鈕;
  • 事件調用 makeRequest() 方法;
  • 請求發出,然後 (onreadystatechange)執行傳遞給 alertContents();
  • alertContents() 檢查響應是否 OK, 然後 alert() test.html 文件內容。
註意 1: 如果服務器返回XML,而不是靜態XML文件,你必須設置response headers 來兼容i.e.。如果你不設置headerContent-Type: application/xml, IE 將會在你嘗試獲取 XML 元素之後拋出一個JavaScript "Object Expected" 錯誤 。 註意 2: 如果你不設置header Cache-Control: no-cache 瀏覽器將會緩存響應不再次提交請求,很難debug。你可以添加永遠不一樣的GET 參數,例如 timestamp 或者 隨機數 (查看 bypassing the cache) 註意 3: 如果 httpRequest 變量是全局的,混雜調用 makeRequest()會覆蓋各自的請求,導致一個競爭的狀態。在一個closure 裏聲明 httpRequest 本地變量 來避免這個問題。 在發生通信錯誤(如服務器崩潰)、onreadystatechange方法會拋出一個異常,當訪問響應狀態。為了緩解這個問題,你可以用ry…catch包裝你的if...then 語句:
function alertContents() {
try {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert(‘There was a problem with the request.‘);
}
}
}
catch( e ) {
alert(‘Caught Exception: ‘ + e.description);
}
}

Step 4 – 使用 XML 響應

在前面的例子裏,在獲取到響應之後,我們用request 對象responseText 屬性獲得 test.html 文件內容。現在讓我們嘗試獲取responseXML 屬性。 首先,讓我們創建一個有效的XML文檔,留著待會我們請求。(test.xml)如下:
<?xml version="1.0" ?>
<root>
I‘m a test.
</root>
在這個腳本裏,我們只要修改請求行為:
...
onclick="makeRequest(‘test.xml‘)">
...
然後在alertContents()裏,我們需要把 alert(httpRequest.responseText); 換為:
var xmldoc = httpRequest.responseXML;
var root_node = xmldoc.getElementsByTagName(‘root‘).item(0);
alert(root_node.firstChild.data);
這裏獲得了responseXML的XMLDocument,然後用 DOM 方法來獲得包含在XML文檔裏面的內容。你可以在here查看test.xml,在here查看修改後的腳本。

Step 5 – 使用數據返回

最後,讓我們來發送一些數據到服務器,然後獲得響應。我們的JavaScript這次將會請求一個動態頁面,test.php將會獲取我們發送的數據然後返回一個計算後的字符串 - "Hello, [user data]!",然後我們alert()出來。 首先我們加一個文本框到HTML,用戶可以輸入他們的姓名:
<label>Your name: 
<input type="text" id="ajaxTextbox" />
</label>
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
Make a request
</span>
我們也給事件處理方法裏面加一行獲取文本框內容,並把它和服務器端腳本的url一起傳遞給 makeRequest() 方法:
  document.getElementById("ajaxButton").onclick = function() { 
var userName = document.getElementById("ajaxTextbox").value;
makeRequest(‘test.php‘,userName);
};
我們需要修改makeRequest()方法來接受用戶數據並且傳遞到服務端。我們將把方法從 GET 改為 POST,把我們的數據包裝成參數放到httpRequest.send():
function makeRequest(url, userName) {

...

httpRequest.onreadystatechange = alertContents;
httpRequest.open(‘POST‘, url);
httpRequest.setRequestHeader(‘Content-Type‘, ‘application/x-www-form-urlencoded‘);
httpRequest.send(‘userName=‘ + encodeURIComponent(userName));
}
如果服務端只返回一個字符串, alertContents() 方法可以和Step 3 一樣。然而,服務端不僅返回計算後的字符串,還返回了原來的用戶名。所以如果我們在輸入框裏面輸入 “Jane”,服務端的返回將會像這樣: {"userData":"Jane","computedString":"Hi, Jane!"} 要在alertContents()使用數據,我們不能直接alert responseText, 我們必須轉換數據然後 alert computedString屬性:
function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
var response = JSON.parse(httpRequest.responseText);
alert(response.computedString);
} else {
alert(‘There was a problem with the request.‘);
}
}
}
test.php 文件如下:
$name = (isset($_POST[‘userName‘])) ? $_POST[‘userName‘] : ‘no name‘;
$computedString = "Hi, " . $name;
$array = [‘userName‘ => $name, ‘computedString‘ => $computedString];
echo json_encode($array);
查看更多DOM方法, 請查看 Mozilla‘s DOM implementation 文檔。

ajax(Asynchronous JavaScript + XML) 技術學習