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

何謂 AJAX?

AJAX 是 Asynchronous JavaScript And XML 的 簡寫,它的裡面非常類似 Dynamic HTML(或者 DHTML),主要的目的在於提高 網頁的互動性(interactivity),速度(speed),以及可用性(usability)。 想想看,如果我們能使一個網頁的互動方式可以達到類似 Microsoft Office 的 境界,那麼網頁的可用性可以達到另一個層次。

其實,這個概念並不是很新,只是這樣的技巧被大量的應用於 Google 的網頁之後, 如 Gmail、Google Maps、和 Google Suggest 等,才被重視,而第一個提出 AJAX 這個名詞的就是 Jesse James Garrett。利用類似技巧的公司還有 Writely、Kiko 等。這樣的概念,開始的人們對於網頁是否會取代 desktop applications 進行 討論,而又進一步的延伸出 What is Web 2.0 的討論。

AJAX 也不是一項單獨的技術,它是由一堆現有的技術所組成,它的組成技術有:

  1. XHTML(或者 HTML)加上 CSS 來作為資料的呈現。
  2. 利用 DOM 以及 Javascript 來進行存取資料(大多為 XML)的處理。
  3. 利用 XMLHttpRequest 物件與遠端的 web server 進行非同步的資料交換。

第一個範例

在之前的 JavaScript 入門中,我們已經給了 HTML 和 CSS 以及 DOM 的 應用範例,因此我們在第一個範例中,介紹 XMLHttpRequest 的用法。 這個範例試圖從遠端取得台中地區的行政區域檔

取得台中的行政區域

使用 AJAX 的時機

想想看,像 Google Maps 的使用中,browser 與 web server 之間需要傳遞非常大量的 圖形資料,如果利用傳統的同步方式,在全部的圖形下載完成之前,我們沒辦法 對網頁進行操作,而使用者點選往左、往右的按鈕後,使用者又得等待另一次 的圖形傳遞。反之,如果我們可以在使用者操作的時候,非同步的下載其它圖形 呢?這樣速度會變快,也不必一再的重複 reload 網頁。(註:依據 IBM McLaughlin 的說法,這些可以動態出現不同內容的地方,經常是由 <div> 或者 <span> 所定義。)

當 AJAX engine 接收使用者全部或者部份的 form data 之後,AJAX engine 會跟 web server 連絡並由 web server 處理完成,並將完成的資料回傳給 AJAX engine, 然後再由 AJAX engine 將成果動態的呈現在網頁上。這些過程,使用者完全不會 感受到,而且由於是非同步的,網頁不會停止接收使用者的操作。

練習題

由 XMLHttpRequest 送出中文資料給 Tomcat

在嘗試 Dojo 和 Yahoo! User Interface Library (YUI) 的時候,才突然發現之前的 AJAX 範例都沒有從 XMLHttpRequest 傳送中文的資料給遠端的 Tomcat servlet。 而發現的原因在於為 Dojo 和 YUI 所寫的程式中,其中一個範例是由 browser 送出 一個中文的(Big5)欄位資料到遠端的 Tomcat servlet 處理,而處理的結果 卻是亂碼。這樣子一來就打亂了我的休假,連續兩個晚上測到凌晨一、兩點 (對一個老人來說,是很大的折磨)。這兩天找了不少資料,目前以 的文章比較有參考價值。尤其,OC'onner 的文章直接說明目前的傳送以及 encoding 的方式並沒有標準,完全要看你所使用的工具而定。看了這個說明之後,測試的方向 就比較明確一些。大概需要檢查的細節有: 目前,已經找出 Microsoft IE 6.x 以及 Firefox 1.5.x 的解決方案了。 測試出來的情形整理如下:(在沒有足夠的資訊之下,很難明確的了解為什麼會有這樣的 encode/decode 結果) 從剛剛的討論結果可以知道 XMLHttpRequest 在送出要求之前,我們需要對 Big5 的資料進行編碼(也就是 encodeURIComponent),而送到 Tomcat servlet 之後, servlet 必須先以 ISO-8859-1 的方式接收之後, 再依據 UTF-8 的方式解碼使資料回到 Big5 的格式,你可以 連結 測試網頁
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Big5">
<script type="text/javascript" language="javascript">
  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); };

    // IE 6.x 和 Firefox 1.5.x 皆要 encodeURI()
    
    url = url + "?name=" +
          encodeURIComponent(document.myform.elements[0].value);
    
    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 mesg = http_request.responseText;
        alert(mesg);
      } else {
        alert('There was a problem with the request.');
      }
    }
  }
</script>
</head>

<body>
<form name="myform">
姓名: <input type="text" name="name"></input>
<input type="button" value="OK" onClick="makeRequest('適當的 servlet URL');"></input>
</form>
</body>
</html>
遠端的 servlet 程式為
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class Hello extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res)
         throws ServletException, IOException
  {
    res.setContentType("text/plain;charset=Big5");
    PrintWriter output = res.getWriter();

    String msg = req.getParameter("name");
    
    msg = new String(msg.getBytes("ISO-8859-1"), "UTF-8");
    

    StringBuffer buf = new StringBuffer();
    buf.append("Hello " + msg);
    buf.append(" , 歡迎使用 AJAX");
    output.println(buf.toString());
    output.close();
  }
}

利用 Dojo Toolkit

想要寫出一個擁有豐富介面的 AJAX 程式,其實有一定的困難。為了讓我們的 AJAX 程式具有"企業級"的水準,我們可以借用一些 AJAX 的程式庫。 目前非常受歡迎、而且又是 open source 的 AJAX 工具有 Dojo Toolkit 以及 Yahoo! User Interface Library

利用 Yahoo! User Interface Library


Last Updated: Monday, 02-Jun-2008 14:01:58 CST
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu