Nhập môn AJAX

Công nghệ AJAX ra đời từ năm 2005, viết tắt của Asynchronous JavaScript and XML, cho phép các trang web ở phía client trao đổi dữ liệu với server mà không làm gián đoạn giao diện người dùng. Các trình duyệt web tương tác với server bằng cách tạo ra các yêu cầu cho trang thông qua hai phương thức là POSTGET. Server xử lí yêu cầu và gửi lại kết quả (HTML, script, css) đến trình duyệt. Mô hình truyền thống như sau:

Nhìn vào mô hình trên chúng ta thấy có hai trở ngại chính là:

  • Do toàn bộ trang được gửi lại từ server nên tạo ra một gánh nặng không cần thiết. Ví dụ trong Contact Form của chúng ta, mỗi lần người dùng nhập thông tin và nhấn Send thì toàn bộ trang sẽ được gửi đến browser, trong khi chỉ có một vài thông tin người dùng nhập là thay đổi còn phần lớn các thành phần như menu, banner, table,…không đổi.
  • Cũng vì toàn bộ trang được gửi trở lại từ server nên những cái đã có trong quá trình tương tác trước đó sẽ được thay bằng những cái mới, quá trình thay thế này sẽ làm cho trang cảm giác như “nhấp nháy”, một hiệu ứng gây khó chịu cho người dùng.

Công nghệ AJAX ra đời để giải quyết những trở ngại trên. Một số lợi ích của AJAX:

  • Cho phép đọc – gửi dữ liệu đến web server
  • Chỉ một phần trang (được yêu cầu) được gửi trở lại từ web server thay vì toàn bộ trang.

Với AJAX, mô hình trao đổi giữa web browsers và web servers sẽ như sau:

Đối tượng XMLHttpRequest

Đối tượng XMLHttpRequest là cốt lõi của AJAX và tất cả các trình duyệt web hiện đại đều hỗ trợ đối tượng XMLHttpRequest.

Đối tượng XMLHttpRequest có thể trao đổi dữ liệu với web server và chỉ cập nhật một phần thay vì toàn bộ trang web.

Tạo một đối tượng XMLHttpRequest

Tạo một đối tượng XMLHttpRequest theo cú pháp:


var variablename = new XMLHttpRequest();

Ví dụ:


var xhttp = new XMLHttpRequest();

Truy cập giữa các domain

Vì lý do bảo mật nên hầu hết các trình duyệt web hiện đại không cho phép trao đổi dữ liệu giữa các domain – nghĩa là, nếu một trang web cố gắng tải một tập tin XML thì cả hai phải thuộc về cùng một máy chủ (server).

Các phương thức (methods) của đối tượng XMLHttpRequest

Như hầu hết các đối tượng, XMLHttpRequest cũng chứa một vài phương thức quan trọng:

Phương thức Mô tả
new XMLHttpRequest() Tạo một đối tượng XMLHttpRequest mới
abort() Huỷ yêu cầu hiện tại
getAllResponseHeaders() Trả về thông tin header
getResponseHeader() Trả về thông tin header được xác định
open(method, url, async, user, psw) Xác định hay mô tả các yêu cầu: method xác định kiểu GET hay POST, url vị trí tập tin trên server, async xác định đồng bộ (false) hay không đồng bộ (true), user tên người dùng, psw mật khẩu người dùng.
send() Gửi yêu cầu đến server dùng GET
send(string) Gửi yêu cầu đến server dùng POST
setRequestHeader() Thiết lập thông tin (dạng cặp label/value) đến header được gửi.

Các thuộc tính(properties) của đối tượng XMLHttpRequest

Thuộc tính Mô tả
onreadystatechange Định nghĩa một hàm sẽ được gọi khi thuộc tính readyState thay đổi.
readyState Trạng thái của đối tượng XMLHttpRequest: 0 yêu cầu không được khởi tạo, 1 kết nối server được thiết lập, 2 yêu cầu được nhận, 3 xử lý yêu cầu, 4 xử lý yêu cầu hoàn tất và sẵn sàng gửi lại browser.
responseText Gửi dữ liệu đến browser như một chuỗi văn bản
responseXML Gửi dữ liệu đến browser theo định dạng XML
status Trả về giá trị số thể hiện trạng thái của một yêu cầu: 200: “OK”, 403: “Forbidden”, 404: “Not Found”,…(Danh sách đầy đủ có thể tham khảo tại https://www.w3schools.com/tags/ref_httpmessages.asp )
statusText Thông điệp tương ứng với status như OK, Forbidden,…(Danh sách đầy đủ có thể tham khảo tại https://www.w3schools.com/tags/ref_httpmessages.asp )

Gửi một yêu cầu đến một server

Để gửi một yêu cầu đến một server chúng ta dùng hai phương thức opensend (send() hay send(string) tuỳ vào kiểu GET hay POST) của đối tượng XMLHttpRequest.

GET hay POST

HTTP (Hypertext Transfer Protocol) là giao thức  được thiết kế để giao tiếp giữa client (có thể là web browsers) và server (có thể là một ứng dụng trên máy tính host một website như Apache, IIS). HTTP làm việc theo cơ chế yêu cầu – đáp ứng (request – response) nhằm giao tiếp giữa client và server theo hai phương thức chủ yếu:

  • GET: yêu cầu dữ liệu từ một nguồn xác định
  • POST: submit dữ liệu đã được xử lý đến một nguồn cụ thể

Bảng sau sẽ so sánh giữa GETPOST

GET POST
Sẽ không có gì thay đổi khi nhấn nút back hay reload trang web Dữ liệu sẽ được gửi lại (re-submitted) server (và trình duyệt sẽ thông báo đến người dùng)
Có thể được bookmark đến trình duyệt Không thể được bookmark
Dữ liệu có thể được lưu trong bộ nhớ tạm (cache) Dữ liệu không được lưu trong bộ nhớ cache
Kiểu mã hoá: application/x-www-form-urlencoded Kiểu mã hoá: application/x-www-form-urlencoded hay multipart/form-data. Dùng mã hoá nhiều phần cho dữ liệu nhị phân
Các tham số có thể được lưu lại trong History của trình duyệt Các tham số không được lưu lại trong History của trình duyệt
GET gửi dữ liệu bằng cách thêm dữ liệu đến URL nên chiều dài của dữ liệu là hạn chế vì chiều dài của URL là hạn chế (2048 kí tự). Vì dữ liệu được thêm trong phần thân của thông điệp HTTP nên chiều dài dữ liệu sẽ không hạn chế.
Chỉ cho phép các kí tự mã ASCII Không hạn chế và chấp nhận cả dữ liệu nhị phân.
Vì dữ liệu là một phần của URL nên sẽ không an toàn vì có thể được thấy bởi mọi người và có thể bị can thiệp để thay đổi nội dung hay chèn mã độc hại. Không nên gửi mật khẩu hay các thông tin nhạy cảm bằng GET. An toàn hơn vì dữ liệu không được lưu trong History hay các tập tin log ở web server và dữ liệu được lưu trong phần thân thông điệp HTTP nên sẽ không được thấy trong URL.

(Có thể tham khảo thêm về giao thức HTTP tại https://www.w3schools.com/tags/ref_httpmethods.asp )

Ví dụ tạo một đối tượng XMLHttpRequest và gửi yêu cầu (kiểu GET) đến server:


var xhttp =new XMLHttpRequest();

xhttp.open("GET", "ajax_info.txt", true);

xhttp.send();

Dùng kiểu POST


xhttp.open("POST", " ajax_info.txt ", true);

xhttp.send();

Có thể gửi thông tin với GET bằng cách thêm thông tin đến tham số url của open() như ví dụ:


xhttp.open("GET", "demo_get2.asp?fname=Henry&lname=Ford", true);

xhttp.send();

Có thể dùng POST để gửi thông tin kiểu form, thêm http header với phương thức setRequestHeader(), như ví dụ sau:


xhttp.open("POST", "ajax_test.asp", true);

xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

xhttp.send("fname=Henry&lname=Ford");

Thuộc tính async

Giá trị của async có thể là true hay false. Tuy nhiên, chúng ta không nên sử dụng giá trị false vì lúc này đối tượng XMLHttpRequest sẽ hoạt động theo nguyên tắc đồng bộ, nghĩa là, javascript sẽ ngừng thực thi cho đến khi máy chủ sẵn sàng đáp ứng. Nếu server bận hay chậm, chương trình có thể bị treo hay ngừng.

Trả lời từ server

Khi trả lời yêu cầu từ client (hay browser), đối tượng XMLHttpRequest sử dụng các thuộc tính và phương thức:

Phương thức Mô tả
getAllResponseHeaders() Trả về thông tin header
getResponseHeader() Trả về thông tin header được xác định

 Các thuộc tính(properties) của đối tượng XMLHttpRequest

Thuộc tính Mô tả
onreadystatechange Định nghĩa một hàm sẽ được gọi khi thuộc tính readyState thay đổi.
readyState Trạng thái của đối tượng XMLHttpRequest: 0 yêu cầu không được khởi tạo, 1 kết nối server được thiết lập, 2 yêu cầu được nhận, 3 xử lý yêu cầu, 4 xử lý yêu cầu hoàn tất và sẵn sàng gửi lại browser.
responseText Gửi dữ liệu đến browser như một chuỗi văn bản
responseXML Gửi dữ liệu đến browser theo định dạng XML
status Trả về giá trị số thể hiện trạng thái của một yêu cầu: 200: “OK”, 403: “Forbidden”, 404: “Not Found”,…(Danh sách đầy đủ có thể tham khảo tại https://www.w3schools.com/tags/ref_httpmessages.asp )
statusText Thông điệp tương ứng với status như OK, Forbidden,…(Danh sách đầy đủ có thể tham khảo tại https://www.w3schools.com/tags/ref_httpmessages.asp )

 Thuộc tính onreadystatechange

Định nghĩa một hàm sẽ được gọi khi yêu cầu nhận được câu trả lời. Ví dụ:


xhttp.onreadystatechange = function() {

   if (this.readyState == 4 && this.status == 200) {

     document.getElementById("demo").innerHTML = this.responseText;

   }

};

xhttp.open("GET", "ajax_info.txt", true);

xhttp.send();

Ví dụ về sử dụng AJAX

Gửi một yêu cầu kiểu GET

– Tạo một tập tin HTML AJAX First Page.html có nội dung như sau:


<!DOCTYPE html>

<html>

  <body>

      <h2>The XMLHttpRequest Object</h2>

      <button onclick="loadDoc()">Submit </button>

      <p id="demo"></p>

      <script>

        function loadDoc() {

          var xhttp = new XMLHttpRequest();

          xhttp.onreadystatechange = function() {
        
               if (this.readyState == 4 && this.status == 200) {

                document.getElementById("demo").innerHTML = this.responseText;

               }

         };

        xhttp.open("GET", "DataPage.php?fname=Ngoc&lname=Minh", true);

        xhttp.send();

      }

     </script>

   </body>

</html>

– Tạo một tập tin PHP DataPage.php có nội dung sau:


<p>

Xin chào các bạn!

<?php

    $fname = $_GET['fname'];

    $lname = $_GET['lname'];

    echo " ".$fname." ".$lname;

?>

</p>

– Ở đây tôi sẽ thực thi hai tập tin này trên server cục bộ (localhost) cổng 8080 và sử dụng gói phần mềm XAMPP. Bật web server ApacheMySQL:

– Đặt hai tập tin trong thư mục htdocs (trên máy tôi là C:\xampp\htdocs)

– Thực thi trang AJAX First Page.html bằng cách gõ localhost:8080/ AJAX First Page.html (lưu ý các khoảng trắng sẽ được trình duyệt tự động thêm %20):

– Nhấn nút Submit để gửi một yêu cầu (kiểu GET) có kèm thêm thông tin đến server (localhost) và kết quả:

Gửi một yêu cầu kiểu POST

– Các bước thực hiện giống trên nhưng các tập tin được chỉnh sửa lại.Tập tin AJAX First Page.html có nội dung như sau:


<!DOCTYPE html>

<html>

  <body>

      <h2>The XMLHttpRequest Object</h2>

      <button onclick="loadDoc()">Submit </button>

      <p id="demo"></p>

      <script>

        function loadDoc() {

           var xhttp = new XMLHttpRequest();

           xhttp.onreadystatechange = function() {

              if (this.readyState == 4 && this.status == 200) {

                  document.getElementById("demo").innerHTML = this.responseText;

               }

           };

          xhttp.open("POST", "DataPage.php", true);

         xhttp.setRequestHeader("Content-type", "application/x-www-form urlencoded");

         xhttp.send("fname=Ngoc&lname=Minh");

      }

     </script>

   </body>

</html>

– Tạo một tập tin PHP DataPage.php sửa lại nội dung sau:


<p>

Xin chào các bạn!

<?php

   $fname = $_POST['fname'];

   $lname = $_POST['lname'];

   echo " ".$fname." ".$lname;

?>

</p>

Hàm callback

Nếu có nhiều nhiệm vụ AJAX trong website, chúng ta sẽ có một hàm thực thi đối tượng XMLHttpRequest và các hàm khác thực thi nhiệm vụ AJAX.

Có thể áp dụng hàm callback – là hàm được chuyển thành tham số của hàm khác. Ví dụ:


loadDoc("url-1", myFunction1);

loadDoc("url-2", myFunction2);

function loadDoc(url, cFunction) {

   var xhttp;

   xhttp = new XMLHttpRequest();
 
   xhttp.onreadystatechange = function() {

   if (this.readyState == 4 && this.status == 200) {

     cFunction(this);

   }

};

xhttp.open("GET", url, true);

xhttp.send();

}

function myFunction1(xhttp) {

  // action goes here

}

function myFunction2(xhttp) {

  // action goes here

}

Làm việc với tập tin XML

AJAX có thể tương tác với tập tin XML thông qua đối tượng XMLHttpRequest. Ví dụ chúng ta có tập tin Data.xml có nội dung như sau:


<Person>

  <Name>

    <firstname> Ngoc </firstname>

    <lastname> Minh </lastname>

  </Name>

  <Name>

    <firstname> That </firstname>

    <lastname> Khiem </lastname>

  </Name>

</Person>

Tạo một yêu cầu (kiểu GET) để lấy thông tin từ tập tin Data.xml:


var xhttp = new XMLHttpRequest();

xhttp.onreadystatechange = function() {

    if (this.readyState == 4 && this.status == 200) {

       myFunction(this);

    }

};

xhttp.open("GET", "Data.xml", true);

xhttp.send();

Hàm myFunction sẽ xử lý thông tin XML nhận được từ server thành một bảng dữ liệu (HTML):


function myFunction(xml) {

   var i;

   var xmlDoc = xml.responseXML;

   var table="<table><tr><th>First Name</th><th>Last Name</th></tr>";

   var x = xmlDoc.getElementsByTagName("Name");

   for (i = 0; i <x.length; i++) {

       table += "<tr><td>" +

       x[i].getElementsByTagName("firstname")[0].childNodes[0].nodeValue +

       "</td><td>" +

       x[i].getElementsByTagName("lastname")[0].childNodes[0].nodeValue +

       "</td></tr>";

   }

   table += "</table>";

   document.getElementById("demo").innerHTML = table;

}

Kết quả khi nhấn Submit:

Tham khảo thêm ASP.NET AJAX

< Cốt lõi JavaScript