AJAX 入門:第一個範例
The following examples had been tested on Mozilla's Firefox and Microsoft's IE. The document is provided as is. You are welcomed to use it for non-commercial purpose.Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
請勿轉貼
看其他教材
在之前的 JavaScript 入門中,我們已經介紹了 XHTML 和 CSS 以及 DOM 的用法以及 應用範例,因此我們在第一個範例中,介紹 XMLHttpRequest 的用法以及它跟傳統 網頁寫法的不同處。在這個範例中,我們試圖從遠端取得台中地區的行政區域檔(該檔案是一個 XML 檔),然後將其內容顯示在網頁上。 傳統非 AJAX 的網頁,大多遵循以下的步驟:先撰寫一個含有 form 標籤的網頁; 以 HTML 原始碼下方的灰色按鈕為例,該按鈕的 HTML 原始碼如下所示:
<form method="POST" action="http://xml.nchu.edu.tw:8080/jlu/servlet/Taichung"> <input type="submit" value="取得台中行政區" /> </form>
取得台中行政區域
開發一個 AJAX 網頁大略可以分成下列幾個步驟:
- 首先,先在網頁上放置必要的 HTML 元件;例如,在這個範例中,我們的 HTML 元件
如下:
<div style="background-image: url(button.gif); background-repeat: no-repeat; font-size: 14px; width: 132px; height: 28px; padding: 5px 0 0 5px; cursor: pointer;" onclick="makeRequest('taichung.xml')"> 取得台中行政區域 </div> <div id="taichung"></div>
- 在跟遠端伺服器要求檔案以前,我們需要產生 XMLHttpRequest 的物件。
跟所有撰寫 JavaScript 時會遇到的問題一樣,在產生 XMLHttpRequest 的物件,
Mozilla 和 Internet Explorer 也有不同的語法,因此處理 AJAX 的 JavaScript
需要判斷你所使用的 browser 是哪一種。根據不同的瀏覽器, XMLHttpRequest 物件
的方式也不同,下列原始碼說明了各自的處理方式:
if (window.XMLHttpRequest) { // 如果是 Mozilla, Safari,... http_request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // 如果是 IE try { // IE 又分成新版和舊版的,其處理方式也不同 // 新版的 IE,目前 IE 9 OK http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { // 舊版的 IE http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } }
- 有了 XMLHttpRequest 的物件之後,就是向遠端要求檔案,在這個範例中,我們
要取得的檔案名稱是 taichung.xml。
http_request.open('GET', 'taichung.xml', true); http_request.send(null);
- open() 的第一個參數是 HTTP 的方法,看你的需要,以及 web server 支援的情形,你可以使用 GET、POST、或者 HEAD。建議使用大寫以符合 HTTP 的標準。
- open() 的第二個參數是你希望取得的資源的 URL。由於安全的機制, 你只能從同一個 web server 上取得資源;也就是說,若瀏覽器正在查看的網頁是 http://example.com/a.html,那麼 a.html 內的 AJAX 程式碼只能跟 http://example.com 提出 URL 的要求。以本網頁為例,由於本網頁 的伺服器是 web.nchu.edu.tw,那麼 taichung.xml 也必須在 web.nchu.edu.tw 上。 (嚴格的說,雖然這裡設定的 URL 只是 taichung.xml,實際上其完整的 URL 是 http://web.nchu.edu.tw/~jlu/classes/xml/ajax/taichung.xml)
- open() 的第三個參數是代表這個呼叫是不是非同步(即 AJAX 的 第一個 A)。因此,在大部分的情形下都是設為 true 代表在跟遠端取得 資源的同時,browser 可以繼續執行 Javascript 的內容。這個時候其實有兩件 事情同時在進行,一個是從遠端取得資料,另一個是繼續執行 JavaScript 的內容, 或者使用者可以繼續處理網頁上的資料,這也就是非同步的定義。
- 如果使用 GET 的方式,send() 的參數為 null。如果
使用 POST 的方式,我們除了要設定 MIME 的類型(如下)之外,
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http_request.send('name=value&anothername=othervalue&so=on');
- 在進行下一個步驟說明之前,我想先說明"非同步的概念"。傳統的(或者同步的) 程式進行方式是:如果呼叫了 open() 以及 send() 之後, 若遠端程式還沒有執行結束並回傳資料,這個程式會一直停在那裏, 而無法繼續執行下一行指令;但是,如果是非同步的程式,在呼叫完 open() 以及 send() 之後,就算遠端還沒有執行完畢, 這個程式可以繼續執行下一行指令。這樣的優勢也造成了一些問題必須解決, 那就是"如果遠端程式執行完了,並將結果傳回來了",非同步執行中的程式 要如何知道這個情形?為了解決這樣的情形,AJAX 採用了事件處理機制。 一旦遠端程式執行結束,它會觸發一個已經完成了的事件,而我們撰寫的 AJAX 程式就可以事先定義一個處理"已經完成了"事件的處理器(在 Javascript 中,該處理器是一個函數)來處理這樣的情形。
- 既然本範例是非同步的進行方式,在執行 open() 以及 send()
之前,我們必須先設定一些事件處理的函數來處理如"已經完成了"的事件。定義事件
處理函數的格式如下:
http_request.onreadystatechange = function(){ // do the thing };
- 一般來說,事件處理函數首先要檢查的是目前 web server 對於我們之前
送出去的 http_request 的處理狀態為何。處理狀態的屬性名稱為 readyState,
它所有可能的值為
- 0 (尚未初始化; 還沒呼叫 open())
- 1 (載入中; http_request 已經設定好了,但是還沒呼叫 send())
- 2 (載入完成; http_request 已經送給 server 了,server 已經開始 處理了,你可以取得 content header 了。)
- 3 (可以互動的; http_request 已經部份完成了,所以有可能取得 部份處理完的資料)
- 4 (完成的; compelte)
if (http_request.readyState == 4) { // everything is good, the response is received } else { // still not ready }
- web server 的處理結束之後,會回傳一個處理結果;例如,我們的要求
完成了,而且所需要的資料也已經回傳了;但是也有可能是,我們的要求完成了,
但是處理結果卻是"找不到檔案"。因此,我們的程式還需要檢查處理
結果,處理結果是放在 status 這個屬性內,因此檢查處理結果
的程式碼如下:
if (http_request.status == 200) { // 可以依照我們的需求來處理 xml 的資料了 } else { // 404 代表檔案不存在,500 代表處理錯誤(Internal Server Error) // 自行決定要如何處理錯誤的情形 }
- 最後,就是接收來自 web server 的資料,http_request 提供兩種方式來
存取資料:
- http_request.responseText 也就是 web server 回傳的資料是 一個字串物件,你需要利用字串的處理函數適當的處理該字串物件。
- http_request.responseXML 也就是 web server 回傳的資料是一份 XMLDocuemnt 的物件,你可以利用 JavaScript 的 DOM APIs 來存取 這份 XML 物件。
- 這個範例的完整原始碼:
<script type="text/javascript" language="javascript"> // 修改自 AJAX: Getting Started - MDC function makeRequest(url) { var http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... http_request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (!http_request) { alert('Giving up :( Cannot create an XMLHTTP instance'); return false; } // 定義事件處理函數為 alterContents() http_request.onreadystatechange = function() { alertContents(http_request); }; http_request.open('GET', url, true); http_request.send(null); } function alertContents(http_request) { if (http_request.readyState == 4) { if (http_request.status == 200) { var xmldoc = http_request.responseXML; var nodes = xmldoc.getElementsByTagName('area'); var mesg = ""; for(var i=0; i<nodes.length; i++) { mesg += nodes[i].firstChild.nodeValue + "\n"; } //alert(mesg); document.getElementById("taichung").innerHTML = mesg; } else { alert('There was a problem with the request.'); } } } </script>
- 大家可以試著將 document.getElementById("taichung").innerHTML = mesg; 換成 alert(mesg);,然後試試看結果有什麼變化。
- 參考資料:尤其是 DOM 以及 XMLHttpRequest 的使用方法。
- Gecko DOM Reference Gecko 是 Mozilla、Firefox、Opera 等瀏覽器的引擎,你需要這個文件來檢查有哪些 DOM 的 APIs 可以使用。
- The XMLHttpRequest Object.
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
您好;
回覆刪除我是一位AJAX的初學者
今天我試圖將您的範例執行,但始終只有顯示"取得台中行政區域"的字樣,之後怎麼點擊這個字樣都沒有任何反應,我用alert("")測示的結果,確定可以跑到http_request.onreadystatechange = function() {alertContents(http_request); };
這一行之前,另外,我有將taichung.xml載下來跟範例碼放在同個資料夾,請問您知道該如何解決這個問題嘛? 謝謝!!!
最主要的原因在於執行"取得台中行政區域"的主機,在 02/02/2013 因為學校整個停電檢修的情形下關機,需要到星期一才有人進機房開機。另一個原因就是屬於跨域呼叫,所有範例建議自行架個 Tomcat 的伺服器。
回覆刪除謝謝您~~~~
刪除可是我已經把xml檔載下來了,那應該就跟伺服器有沒有開沒關係了吧?
是因為xml跟html只單純放在電腦中的同一個資料夾無法產生連結的緣故嘛?
接著
我試著架設出一個伺服器再把xml檔跟HTML檔放在一起 看這樣可不可以讀到xml檔
感謝您這麼迅速就回文!!!