Ajax mở đường cho các ứng dụng Web tốt hơn
Philip McCarthy, Nhà Phát triển, SmartStream Technologies Ltd

Ajax hoặc JavaScript và XML không đồng bộ, là một cách tiếp cận để phát triển ứng dụng Web có sử dụng tạo kịch bản lệnh phía-khách để trao đổi dữ liệu với máy chủ Web. Kết quả là, các trang Web được cập nhật động mà không phải làm mới toàn bộ trang khi ngắt luồng tương tác. Với Ajax, bạn có thể tạo các giao diện người dùng ứng dụng Web động hơn, phong phú hơn để tiếp cận trực tiếp và khả năng sử dụng các ứng dụng máy tính bản địa.

Ajax không là một công nghệ, nó còn hơn một mẫu — một cách để nhận biết và mô tả một kỹ thuật thiết kế có lợi. Về ý nghĩa nào đó Ajax là mới nên nhiều nhà phát triển chỉ đang bắt đầu nhận biết về nó, nhưng tất cả các thành phần triển khai thực hiện một ứng dụng Ajax đã tồn tại trong nhiều năm. Các tin đồn hiện nay là do sự nổi lên trong năm 2004 và 2005 của các giao diện người dùng (UI) động quan trọng dựa vào công nghệ Ajax, đáng chú ý nhất là các ứng dụng GMail và Maps của Google và trang chia sẻ hình ảnh Flickr. Các UI này đã có đủ tính đột phá được một số nhà phát triển gọi là “Web 2.0″, khiến người ta quan tâm nhiều đến ứng dụng Ajax.

Trong loạt bài này, tôi sẽ cung cấp cho bạn tất cả các công cụ mà bạn cần để bắt đầu phát triển các ứng dụng riêng của bạn khi sử dụng Ajax. Trong bài viết đầu tiên này, tôi sẽ giải thích các khái niệm đằng sau Ajax và trình diễn các bước cơ bản để tạo ra một giao diện Ajax cho ứng dụng Web dựa trên Java. Tôi sẽ sử dụng các ví dụ mã để biểu thị cả mã Java phía máy chủ lẫn mã JavaScript phía máy khách để tạo ra các ứng dụng Ajax động. Cuối cùng, tôi sẽ chỉ ra một số khó khăn của cách tiếp cận Ajax, cũng như các khả năng sử dụng rộng hơn và về khả năng tiếp cận mà bạn cần cân nhắc khi tạo các ứng dụng Ajax.

Một giỏ mua hàng tốt hơn

Bạn có thể sử dụng Ajax để nâng cao các ứng dụng Web truyền thống, sắp xếp hợp lý hóa tương tác bằng cách loại bỏ việc nạp trang. Để giải thích điều này, tôi sẽ sử dụng các ví dụ đơn giản về một giỏ mua hàng được tự động cập nhật khi các mục hàng được thêm vào giỏ. Được tích hợp trong cửa hàng trực tuyến, cách tiếp cận này sẽ cho phép những người dùng tiếp tục duyệt và thêm các mục hàng vào giỏ hàng của họ mà không cần phải chờ sau mỗi lần nhấp chuột để cập nhật một trang đầy đủ. Trong khi một số mã trong bài viết này dành riêng cho ví dụ giỏ hàng, các kỹ thuật được minh họa có thể được áp dụng cho bất kỳ ứng dụng Ajax nào. Liệt kê 1 cho thấy mã HTML được ví dụ giỏ mua hàng này sử dụng. Tôi sẽ quay lại mã HTML này trong suốt bài viết.

Liệt kê 1. Các đoạn mã có liên quan của ví dụ giỏ mua hàng

<!-- Table of products from store's catalog, one row per item -->
<th>Name</th> <th>Description</th> <th>Price</th> <th></th>
...
<tr>
  <!-- Item details -->
  <td>Hat</td> <td>Stylish bowler hat</td> <td>$19.99</td>
  <td>
    <!-- Click button to add item to cart via Ajax request -->
    <button onclick="addToCart('hat001')">Add to Cart</button>
  </td>
</tr>
...

<!-- Representation of shopping cart, updated asynchronously -->
<ul id="cart-contents">

  <!-- List-items will be added here for each item in the cart -->
  
</ul>

<!-- Total cost of items in cart displayed inside span element -->
Total cost: <span id="total">$0.00</span>

Chu trình vòng tròn (roundtrip) của Ajax

Một tương tác Ajax bắt đầu bằng một đối tượng JavaScript tên là XMLHttpRequest (Yêu cầu XMLHttp). Như tên cho thấy, nó cho phép một kịch bản lệnh phía máy khách thực hiện các yêu cầu HTTP và nó sẽ phân tích cú pháp câu trả lời của máy chủ XML. Bước đầu tiên trong chu trình vòng tròn Ajax là tạo một cá thể XMLHttpRequest. Phương thức HTTP để sử dụng cho các yêu cầu (GET hoặc POST) và URL đích sau đó được đặt trên đối tượng XMLHttpRequest.

Bây giờ, bạn có nhớ tại sao chữ a đầu tiên trong Ajax là chữ viết tắt của không đồng bộ (asynchronous) không? Khi bạn gửi yêu cầu HTTP đó, bạn không muốn trình duyệt bị treo khi chờ máy chủ trả lời. Thay vào đó, bạn muốn nó tiếp tục phản ứng lại với sự tương tác của người dùng với trang đó và xử lý trả lời đến từ máy chủ. Để thực hiện việc này, bạn có thể đăng ký một hàm gọi lại với XMLHttpRequest rồi gửi đi XMLHttpRequest không đồng bộ. Rồi kiểm soát các trả về tới trình duyệt, trừ ra hàm gọi lại sẽ được gọi khi trả lời của máy chủ đến.

Trên máy chủ Web Java, yêu cầu đến giống như bất kỳ HttpServletRequest khác nào. Sau khi phân tích cú pháp các tham số yêu cầu, servlet gọi logic ứng dụng cần thiết, tuần tự hóa trả lời của nó thành XML và ghi nó vào HttpServletResponse.

Quay lại phía máy khách, hàm gọi lại được đăng ký trên XMLHttpRequest bây giờ được gọi để xử lý tài liệu XML do máy chủ trả về. Cuối cùng, giao diện người dùng được cập nhật đáp lại dữ liệu từ máy chủ, khi sử dụng JavaScript để thao tác HTML DOM của các trang. Hình 1 là một sơ đồ trình tự của chu trình vòng tròn Ajax.

Hình 1. Chu trình vòng tròn Ajax

Sơ đồ chu trình vòng tròn Ajax
Sơ đồ chu trình vòng tròn Ajax

Bây giờ bạn có một khung nhìn mức cao về chu trình vòng tròn Ajax, tôi sẽ phóng to để xem xét chi tiết hơn ở mỗi bước trên đường đi. Quay trở lại Hình 1 nếu bạn không tìm thấy vị trí của mình, trình tự này không hoàn toàn dễ hiểu do tính chất không đồng bộ của cách tiếp cận Ajax.

Gửi đi một XMLHttpRequest

Tôi sẽ xuất phát tại điểm bắt đầu của trình tự Ajax: tạo và gửi đi một XMLHttpRequest từ trình duyệt. Thật không may, phương thức để tạo ra một XMLHttpRequest khác với từ trình duyệt đến trình duyệt. Hàm JavaScript trong Liệt kê 2 làm phẳng các nếp gấp phụ thuộc trình duyệt này, tìm ra cách tiếp cận đúng cho trình duyệt hiện tại và trả về một XMLHttpRequest đã sẵn sàng để sử dụng. Thật tốt để nghĩ về điều này như là mã soạn sẵn: chỉ cần chép nó vào trong thư viện JavaScript của bạn và sử dụng nó khi bạn cần một XMLHttpRequest.

Liệt kê 2. Tạo một XMLHttpRequest của trình duyệt chéo

/*
 * Returns a new XMLHttpRequest object, or false if this browser
 * doesn't support it
 */
function newXMLHttpRequest() {

  var xmlreq = false;

  if (window.XMLHttpRequest) {

    // Create XMLHttpRequest object in non-Microsoft browsers
    xmlreq = new XMLHttpRequest();

  } else if (window.ActiveXObject) {

    // Create XMLHttpRequest via MS ActiveX
    try {
      // Try to create XMLHttpRequest in later versions
      // of Internet Explorer

      xmlreq = new ActiveXObject("Msxml2.XMLHTTP");

    } catch (e1) {

      // Failed to create required ActiveXObject

      try {
        // Try version supported by older versions
        // of Internet Explorer

        xmlreq = new ActiveXObject("Microsoft.XMLHTTP");

      } catch (e2) {

        // Unable to create an XMLHttpRequest with ActiveX
      }
    }
  }

  return xmlreq;
}

Sau đó, tôi sẽ thảo luận các kỹ thuật để xử lý các trình duyệt không hỗ trợ XMLHttpRequest. Bây giờ, các ví dụ giả định rằng hàm newXMLHttpRequest từ Liệt kê 2 sẽ luôn luôn trả về một cá thể XMLHttpRequest.

Quay trở lại kịch bản ví dụ giỏ mua hàng, tôi muốn gọi một sự tương tác Ajax bất cứ khi nào người dùng nhấn vào nút Add to Cart (Thêm vào giỏ hàng) với một mục hàng. Trình xử lý (handler) onclick có tên là addToCart() có trách nhiệm cập nhật trạng thái giỏ hàng thông qua một cuộc gọi Ajax (xem Liệt kê 1). Như thể hiện trong Liệt kê 3, điều đầu tiên mà addToCart() cần làm là nhận một cá thể XMLHttpRequest bằng cách gọi hàm newXMLHttpRequest() từ Liệt kê 2. Tiếp theo, nó đăng ký một hàm gọi lại để nhận được trả lời của máy chủ (tôi sẽ giải thích chi tiết điều này sau; xem Liệt kê 6).

Do yêu cầu này sẽ thay đổi trạng thái trên máy chủ, tôi sẽ sử dụng một HTTP POST để làm chứng thư. Việc gửi dữ liệu thông qua POST yêu cầu ba bước. Đầu tiên, tôi cần phải mở một kết nối POST tới nguồn tài nguyên của máy chủ mà tôi giao tiếp — trong trường hợp này một servlet được ánh xạ đến địa chỉ URL cart.do. Tiếp theo, tôi đặt ra một tiêu đề trên XMLHttpRequest để nói rằng nội dung của yêu cầu là dữ liệu biểu mẫu có mã hóa. Cuối cùng, tôi gửi yêu cầu đó với dữ liệu biểu mẫu có mã hóa làm phần thân.

Liệt kê 3 kết hợp các bước này lại với nhau.

Liệt kê 3. Gửi một XMLHttpRequest Thêm vào giỏ hàng

/*
 * Adds an item, identified by its product code, 
 * to the shopping cart
 * itemCode - product code of the item to add.
 */
function addToCart(itemCode) {

  // Obtain an XMLHttpRequest instance
  var req = newXMLHttpRequest();

  // Set the handler function to receive callback notifications
  // from the request object
  var handlerFunction = getReadyStateHandler(req, updateCart);
  req.onreadystatechange = handlerFunction;
  
  // Open an HTTP POST connection to the shopping cart servlet.
  // Third parameter specifies request is asynchronous.
  req.open("POST", "cart.do", true);

  // Specify that the body of the request contains form data
  req.setRequestHeader("Content-Type", 
                       "application/x-www-form-urlencoded");

  // Send form encoded data stating that I want to add the 
  // specified item to the cart.
  req.send("action=add&item="+itemCode);
}

Và ngay sau đó, bạn đã nhìn thấy phần đầu tiên của việc thiết lập chu trình vòng tròn Ajax — cụ thể là việc tạo ra và gửi đi yêu cầu HTTP từ phía máy khách. Tiếp theo là mã servlet Java được sử dụng để xử lý yêu cầu này.

Xử lý yêu cầu servlet

Việc xử lý một XMLHttpRequest bằng một servlet phần lớn giống như việc xử lý một yêu cầu HTTP thông thường từ trình duyệt. Dữ liệu biểu mẫu đã mã hóa được gửi trong phần thân của yêu cầu của POST có thể được các cuộc gọi HttpServletRequest.getParameter() thu nhận. Các yêu cầu Ajax tham gia vào HttpSession giống như các yêu cầu Web thông thường từ ứng dụng. Điều này có ích cho kịch bản trong ví dụ giỏ mua hàng vì nó cho phép tôi tóm lược trạng thái giỏ hàng của người dùng trong một JavaBean và vẫn tiếp tục trạng thái đó cho phiên làm việc giữa các yêu cầu.

Liệt kê 4 là một phần của một servlet đơn giản có xử lý các yêu cầu Ajax để cập nhật giỏ hàng. Một bean Cart được lấy từ phiên làm việc của người dùng và trạng thái của nó được cập nhật theo các tham số yêu cầu. Cart sau đó được tuần tự hóa tới XML và XML đó được ghi vào ServletResponse. Quan trọng là thiết lập kiểu nội dung cho application/xml, nếu không XMLHttpRequest sẽ không phân tích cú pháp nội dung trả lời trong một XML DOM.

Liệt kê 4. Mã servlet để xử lý các yêu cầu Ajax

public void doPost(HttpServletRequest req, 
  HttpServletResponse res)
      throws java.io.IOException {

  Cart cart = getCartFromSession(req);

  String action = req.getParameter("action");
  String item = req.getParameter("item");
  
  if ((action != null)&&(item != null)) {

    // Add or remove items from the Cart
    if ("add".equals(action)) {
      cart.addItem(item);

    } else if ("remove".equals(action)) {
      cart.removeItems(item);

    }
  }

  // Serialize the Cart's state to XML
  String cartXml = cart.toXml();

  // Write XML to response.
  res.setContentType("application/xml");
  res.getWriter().write(cartXml);
}

Liệt kê 5 cho thấy một ví dụ về XML được phương thức Cart.toXml() tạo ra. Nó khá dễ hiểu. Lưu ý thuộc tính generated (được tạo ra) trên phần tử cart, là một dấu thời gian được System.currentTimeMillis() tạo ra.

Liệt kê 5. Ví dụ tuần tự hóa XML của đối tượng Cart

<?xml version="1.0"?>
<cart generated="1123969988414" total="$171.95">
  <item code="hat001">
    <name>Hat</name>
    <quantity>2</quantity>
  </item>
  <item code="cha001">
    <name>Chair</name>
    <quantity>1</quantity>
  </item>
  <item code="dog001">
    <name>Dog</name>
    <quantity>1</quantity>
  </item>
</cart>

Nếu bạn xem xét Cart.java trong mã nguồn ứng dụng có sẵn từ phần Tải về, bạn sẽ thấy rằng XML được tạo ra đơn giản bằng cách gắn thêm các chuỗi lại với nhau. Khi chỉ vừa đủ cho ví dụ này, thị việc này gần như cũng là cách xấu nhất để tạo ra XML từ mã Java. Tôi sẽ đề xuất một số cách tiếp cận tốt hơn trong phần tiếp theo của loạt bài này.

Vì vậy, bây giờ bạn đã biết cách CartServlet đáp ứng với một XMLHttpRequest. Điều kế tiếp là trả về phía máy khách, ở đó bạn có thể xem cách trả lời của XML được sử dụng để cập nhật trạng thái trang.

Xử lý trả lời bằng JavaScript

Đặc tính readyState của XMLHttpRequest là một giá trị số cho trạng thái chu trình của yêu cầu. Nó thay đổi từ 0 ứng với “chưa khởi động” đến 4 ứng với “hoàn thành”. Mỗi khi readyState thay đổi, sự kiện readystatechange bắt đầu thực hiện và gọi hàm trình xử lý được gắn kèm qua đặc tính onreadystatechange.

Trong Liệt kê 3, bạn thấy cách hàm getReadyStateHandler() đã được gọi để tạo ra một hàm trình xử lý. Hàm trình xử lý này sau đó đã được gán cho đặc tính onreadystatechange. Hàm getReadyStateHandler() khai thác một thực tế rằng các hàm là đối tượng lớp đầu tiên trong JavaScript. Điều này có nghĩa là các hàm có thể là các tham số cho các hàm khác và cũng có thể tạo và trả về các hàm khác. Đây là công việc của getReadyStateHandler() để trả về một hàm kiểm tra xem XMLHttpRequest đã hoàn thành chưa và chuyển trả lời XML lên hàm trình xử lý được trình gọi xác định. Liệt kê 6 là mã cho hàm getReadyStateHandler().

Liệt kê 6. Hàm getReadyStateHandler ()

/*
 * Returns a function that waits for the specified XMLHttpRequest
 * to complete, then passes its XML response
 * to the given handler function.
 * req - The XMLHttpRequest whose state is changing
 * responseXmlHandler - Function to pass the XML response to
 */
function getReadyStateHandler(req, responseXmlHandler) {

  // Return an anonymous function that listens to the 
  // XMLHttpRequest instance
  return function () {

    // If the request's status is "complete"
    if (req.readyState == 4) {
      
      // Check that a successful server response was received
      if (req.status == 200) {

        // Pass the XML payload of the response to the 
        // handler function
        responseXmlHandler(req.responseXML);

      } else {

        // An HTTP problem has occurred
        alert("HTTP error: "+req.status);
      }
    }
  }
}


Các mã trạng thái HTTP

Trong Liệt kê 6, đặc tính status (trạng thái) của XMLHttpRequest được thử nghiệm để xem yêu cầu đó đã hoàn thành thành công chưa. status chứa mã trạng thái HTTP của trả lời của máy chủ. Khi thực hiện các yêu cầu đơn giản GET và POST bạn có thể giả định rằng bất kỳ mã nào khác 200 (OK) là một lỗi. Nếu máy chủ gửi một trả lời chuyển hướng (ví dụ, 301 hoặc 302), thì trình duyệt tiếp tục chuyển hướng trong suốt và tìm nguồn tài nguyên từ vị trí mới; XMLHttpRequest không thấy mã trạng thái chuyển hướng. Ngoài ra, trình duyệt sẽ tự động thêm một tiêu đề Cache-Control: no-cache cho tất cả các XMLHttpRequest, do đó mã máy khách sẽ không bao giờ phải đối phó với trả lời máy chủ 304 (không đổi).

Về getReadyStateHandler()

getReadyStateHandler() là một đoạn mã tương đối phức tạp, đặc biệt là nếu bạn không sử dụng để đọc JavaScript. Thỏa hiệp ở đây là việc đặt hàm này trong thư viện JavaScript, bạn chỉ có thể xử lý các trả lời máy chủ Ajax mà không cần phải đối phó với các phần nội tại của XMLHttpRequest. Điều quan trọng là bạn hiểu cách sử dụng getReadyStateHandler() trong mã của riêng mình.

Trong Liệt kê 3, bạn thấy getReadyStateHandler() được gọi như sau: handlerFunction = getReadyStateHandler(req, updateCart). Hàm được getReadyStateHandler() trả về trong trường hợp này sẽ kiểm tra xem XMLHttpRequest trong biến req đã hoàn thành chưa và rồi gọi một hàm có tên updateCart với XML trả lời.

Trích xuất dữ liệu giỏ hàng

Liệt kê 7 là mã updateCart() của chính nó. Hàm kiểm tra tư liệu XML giỏ mua hàng bằng cách sử dụng các cuộc gọi DOM và cập nhật trang Web (xem Liệt kê 1) để phản ánh các nội dung giỏ hàng mới. Ở đây tập trung vào các cuộc gọi được sử dụng để trích xuất dữ liệu từ XML DOM. Thuộc tính generated (được tạo ra) trên phần tử cart (giỏ mua hàng), một dấu thời gian được tạo ra khi Cart được tuần tự hóa theo XML, được kiểm tra để đảm bảo rằng dữ liệu giỏ hàng mới hơn không bị dữ liệu giỏ hàng cũ ghi đè lên. Các yêu cầu Ajax vốn không đồng bộ, do đó việc kiểm tra này đảm bảo an toàn đối với các trả lời từ máy chủ đến không theo trình tự.

Liệt kê 7. Cập nhật trang để phản ánh tư liệu XML của giỏ hàng

function updateCart(cartXML) {

 // Get the root "cart" element from the document
 var cart = cartXML.getElementsByTagName("cart")[0];

 // Check that a more recent cart document hasn't been processed
 // already
 var generated = cart.getAttribute("generated");
 if (generated > lastCartUpdate) {
   lastCartUpdate = generated;

   // Clear the HTML list used to display the cart contents
   var contents = document.getElementById("cart-contents");
   contents.innerHTML = "";

   // Loop over the items in the cart
   var items = cart.getElementsByTagName("item");
   for (var I = 0 ; I < items.length ; I++) {

     var item = items[I];

     // Extract the text nodes from the name and quantity elements
     var name = item.getElementsByTagName("name")[0]
                                               .firstChild.nodeValue;
                                               
     var quantity = item.getElementsByTagName("quantity")[0]
                                               .firstChild.nodeValue;

     // Create and add a list item HTML element for this cart item
     var li = document.createElement("li");
     li.appendChild(document.createTextNode(name+" x "+quantity));
     contents.appendChild(li);
   }
 }
// Update the cart’s total using the value from the cart document
document.getElementById(“total”).innerHTML =
cart.getAttribute(“total”);
}

Và ngay sau đó, hành trình có các lần dừng lại ngắn của chu trình vòng tròn Ajax hoàn thành, mặc dù bạn có thể muốn nhận được ứng dụng Web đang chạy và xem nó hoạt động (xem phần Tải về). Ví dụ này rất đơn giản, có nhiều phạm vi để cải tiến. Hiện tại tôi đã tính đến mã phía máy chủ để loại bỏ các mục khỏi giỏ hàng, nhưng không có cách nào để truy cập nó từ giao diện người dùng. Để có một bài tập tốt, hãy cố gắng cải thiện hơn mã JavaScript hiện có của ứng dụng để thực hiện chức năng này.

Những thách thức của việc sử dụng Ajax

Như với bất kỳ công nghệ nào, có rất nhiều cách sai lầm với Ajax. Một số trong những vấn đề tôi thảo luận ở đây hiện đang thiếu các giải pháp dễ dàng nhưng sẽ được cải tiến khi Ajax đã hoàn thiện. Khi cộng đồng nhà phát triển thu được kinh nghiệm phát triển ứng dụng Ajax, các cách thực hành và hướng dẫn tốt nhất sẽ được viết thành tài liệu.

Tính sẵn sàng của XMLHttpRequest

Một trong những vấn đề lớn nhất ở phía trước các nhà phát triển Ajax là cách trả lời khi XMLHttpRequest chưa sẵn sàng. Trong khi đa số các trình duyệt hiện đại hỗ trợ XMLHttpRequest, sẽ luôn có một số ít người dùng có trình duyệt của mình không hỗ trợ hay trình duyệt của họ thiết lập bảo mật ngăn việc sử dụng XMLHttpRequest. Nếu bạn đang phát triển một ứng dụng Web được triển khai trên một mạng nội bộ công ty, bạn có thể có đủ tiện nghi để xác định những trình duyệt nào được hỗ trợ và giả định XMLHttpRequest luôn luôn có sẵn. Nếu bạn đang triển khai trên Web công cộng, tất nhiên phải lưu ý rằng với cách quá tự tin vào XMLHttpRequest có sẵn, bạn đang có khả năng ngăn người dùng sử dụng các trình duyệt cũ hơn, các trình duyệt cho người khuyết tật hoặc trình duyệt đơn giản trên các thiết bị cầm tay sử dụng ứng dụng của bạn.

Vì vậy, bạn nên cố gắng để làm cho ứng dụng của bạn “giảm duyên dáng” đi và duy trì chức năng trong các trình duyệt không hỗ trợ XMLHttpRequest. Trong ví dụ giỏ mua hàng, cách tốt nhất làm giảm là ứng dụng sẽ có nút Add to Cart thực hiện gửi đi biểu mẫu thường xuyên, làm mới trang để phản ánh trạng thái cập nhật của giỏ hàng. Hành vi của Ajax có thể được thêm vào trang thông qua JavaScript một khi trang được nạp, gắn thêm một hàm trình xử lý JavaScript cho mỗi nút Add to Cart chỉ khi XMLHttpRequest đã có sẵn. Một cách tiếp cận khác là để phát hiện XMLHttpRequest khi người dùng đăng nhập vào và sau đó dùng hoặc làm một phiên bản Ajax của ứng dụng hoặc một phiên bản dựa trên biểu mẫu thông thường khi thích hợp.

Các mối quan tâm về khả năng sử dụng

Một số vấn đề về khả năng sử dụng xung quanh các ứng dụng Ajax phổ biến hơn. Chẳng hạn, điều quan trọng là cho người dùng biết rằng nguồn vào của họ đã được đăng ký, vì các cơ chế phản hồi thông thường của con trỏ đồng hồ cát và việc quay tròn trình duyệt “throbber” không áp dụng cho các XMLHttpRequest. Một kỹ thuật dùng để thay thế các nút Submit (Gửi đi) với một thông báo kiểu ” Now updating…” (Bây giờ đang cập nhật …) để người dùng không liên tục nhấn vào các nút trong khi chờ đợi trả lời.

Vấn đề khác là người dùng có thể không nhận thấy rằng các phần của trang mà họ đang xem đã được cập nhật. Bạn có thể làm dịu bớt vấn đề này bằng cách sử dụng nhiều kỹ thuật trực quan để thu hút một cách khôn khéo mắt của người dùng đến các vùng cập nhật của trang. Các vấn đề khác do việc cập nhật các trang với Ajax gây ra bao gồm “phá vỡ” nút quay về của trình duyệt và URL trong thanh địa chỉ không phản ánh toàn bộ trạng thái của trang, ngăn ngừa đánh dấu. Xem phần Tài nguyên với các bài viết tập trung đặc biệt vào các vấn đề về khả năng sử dụng của các ứng dụng Ajax.

Nạp máy chủ

Việc triển khai thực hiện một giao diện người dùng Ajax thay cho một giao diện người dùng theo mẫu thông thường có thể làm tăng đáng kể số lượng các yêu cầu được thực hiện với máy chủ. Ví dụ, một tìm kiếm Web của Google thường xuyên gây ra một sự truy cập vào máy chủ, xảy ra khi người sử dụng gửi biểu mẫu tìm kiếm. Tuy nhiên, Google Suggest thường cố gắng tự động hoàn thành thời hạn tìm kiếm của bạn, sẽ gửi một số các yêu cầu đến máy chủ như các kiểu người dùng. Khi phát triển một ứng dụng Ajax, hãy có ý thức về việc bạn sắp gửi đến máy chủ bao nhiêu yêu cầu và kết quả nạp máy chủ mà việc này sẽ gây ra. Bạn có thể làm giảm nhẹ việc nạp máy chủ bằng cách tạo tầng đệm cho các yêu cầu trên máy khách và nhớ nhanh các trả lời của máy chủ trên máy khách, khi thích hợp. Bạn cũng nên cố gắng thiết kế các ứng dụng Ajax Web của bạn để cho có thể thực hiện càng hợp lí càng tốt trên máy khách, không cần phải liên lạc với máy chủ.

Đối phó với sự không đồng bộ

Để hiểu rằng không có một sự bảo đảm nào là các XMLHttpRequest sẽ hoàn thành theo thứ tự mà chúng được gửi đi là rất quan trọng. Thật vậy, bạn nên cho rằng chúng sẽ không thực hiện theo thứ tự và thiết kế ứng dụng của bạn với điều này trong tâm trí. Trong ví dụ giỏ mua hàng, một dấu cập nhật thời gian cuối cùng đã được sử dụng để đảm bảo rằng dữ liệu giỏ mua hàng mới hơn sẽ không bị dữ liệu cũ ghi đè (xem Liệt kê 7). Cách tiếp cận rất thô sơ này thực hiện cho kịch bản giỏ mua hàng, nhưng không thể cho các kịch bản khác. Hãy xem xét tại thời điểm thiết kế bạn sẽ đối phó với các trả lời của máy chủ không đồng bộ như thế nào.


Kết luận

Bây giờ bạn cần phải có một sự hiểu biết tốt về các nguyên tắc cơ bản của Ajax và một kiến thức về các thành phần cơ bản của các thành phần phía máy khách và phía máy chủ có tham gia tương tác Ajax. Đây là các khối tạo dựng của một ứng dụng Web Ajax dựa trên Java. Ngoài ra, bạn cũng nên hiểu một số vấn đề thiết kế mức cao đi kèm tiếp cận Ajax. Việc tạo một ứng dụng Ajax thành công đòi hỏi một cách tiếp cận toàn diện — từ thiết kế giao diện người dùng thông qua thiết kế JavaScript đến kiến trúc phía máy chủ — nhưng bây giờ bạn nên được trang bị những kiến thức Ajax lõi cần thiết để xem xét các khía cạnh khác này.

Đó là tin tốt nếu bạn đang cảm thấy nản lòng bởi sự phức tạp của việc viết một ứng dụng Ajax lớn bằng cách sử dụng các kỹ thuật được thể hiện ở đây. Tùy theo các khung công tác như Struts, Spring và Hibernate đã tiến triển tới việc phát triển ứng dụng Web trừu tượng cách xa khỏi các chi tiết mức thấp của Servlet API và JDBC, do đó các bộ công cụ đang xuất hiện để phát triển Ajax dễ dàng. Một số trong các khung công tác này chỉ tập trung vào phía khách, cung cấp các cách thức dễ dàng để thêm các hiệu ứng trực quan vào các trang web của bạn hoặc sắp xếp hợp lý việc sử dụng XMLHttpRequest. Các khung công tác khác tiến xa hơn, đưa ra các phương tiện để tự động tạo các giao diện Ajax từ mã phía máy chủ. Các khung công tác này cố gắng để hoàn thành công việc cho bạn, để bạn có thể tham gia một cách tiếp cận mức cao hơn để phát triển Ajax. Tôi sắp xem xét một số trong số các khung công tác đó trong loạt bài này.

Cộng đồng Ajax đang phát triển nhanh và có rất nhiều thông tin có giá trị ngoài cộng đồng này. Trước khi đọc bài viết tiếp theo trong loạt bài này, tôi khuyên bạn nên tham khảo các bài viết được liệt kê trong phần tài nguyên, đặc biệt khi bạn mới bắt đầu đến với Ajax hoặc phát triển phía máy khách. Bạn cũng nên dành một chút thời gian để nghiên cứu mã nguồn ví dụ và suy nghĩ về cách để cải thiện nó.

Nguồn: ibm.com