AJAX – Cách nhận và xử lý phản hồi từ Server trong JavaScript

Javascript nâng cao | by Học Javascript

AJAX (Asynchronous JavaScript and XML) chính là kỹ thuật nổi bật cho phép các trang web có thể gửi và nhận dữ liệu từ server một cách linh hoạt và hiệu quả. Một trong những phần cốt lõi của AJAX chính là khả năng xử lý phản hồi từ server – bởi mọi dữ liệu cần hiển thị, cập nhật hay phản hồi cho người dùng đều phụ thuộc vào dữ liệu mà server gửi về.

Bài viết này sẽ giúp bạn hiểu rõ cách thức JavaScript nhận và xử lý phản hồi từ server thông qua các công cụ như XMLHttpRequestFetch API, từ đó ứng dụng vào các tình huống thực tế như tìm kiếm tức thì, hiển thị danh sách sản phẩm, hay cập nhật thông tin theo thời gian thực.

Tổng quan về AJAX và vai trò của phản hồi từ server trong JavaScript

AJAX là gì?

AJAX (Asynchronous JavaScript and XML) là một kỹ thuật lập trình web cho phép trang web gửi và nhận dữ liệu từ máy chủ mà không cần tải lại toàn bộ trang. Thay vì refresh toàn trang, AJAX giúp cập nhật từng phần nội dung động – như khi tìm kiếm gợi ý, gửi biểu mẫu, hoặc tải thêm nội dung.

AJAX không phải là một công nghệ độc lập, mà là sự kết hợp của nhiều thành phần:

  • HTML/CSS – hiển thị nội dung.

  • JavaScript – xử lý logic và tương tác người dùng.

  • XMLHttpRequest (hoặc Fetch API) – giao tiếp với server.

  • JSON/XML – định dạng dữ liệu trao đổi.

Tại sao phản hồi từ server lại quan trọng?

Phản hồi (response) là kết quả mà server trả về sau khi nhận yêu cầu từ client (trình duyệt). Dữ liệu phản hồi chính là nội dung mà người dùng cần: danh sách sản phẩm, thông tin tài khoản, trạng thái đơn hàng, hay thông báo lỗi.

Việc xử lý phản hồi đúng cách giúp:

  • Hiển thị thông tin chính xác và kịp thời.

  • Thông báo rõ ràng cho người dùng nếu có lỗi xảy ra.

  • Cập nhật nội dung trang một cách mượt mà.

Phân biệt giữa request và response

Thành phần Ý nghĩa
Request Yêu cầu gửi từ trình duyệt đến server. Có thể là GET, POST, PUT...
Response Phản hồi từ server sau khi xử lý xong yêu cầu.

Ví dụ: Khi bạn nhập từ khóa tìm kiếm và nhấn Enter, trình duyệt gửi request đến server; server xử lý và trả về response là danh sách gợi ý.

Một số loại phản hồi phổ biến

  • JSON (JavaScript Object Notation):
    Loại dữ liệu phổ biến nhất hiện nay. Dễ xử lý trong JavaScript, thích hợp cho API.

  • Text/Plain:
    Dữ liệu thuần văn bản, thường dùng trong các phản hồi đơn giản hoặc thông báo.

  • XML:
    Định dạng cũ hơn, từng phổ biến với AJAX, nhưng nay ít dùng hơn JSON.

  • HTML:
    Một số hệ thống có thể trả về đoạn mã HTML để chèn trực tiếp vào trang.

Nếu bạn muốn, mình có thể viết tiếp phần III về cách nhận phản hồi từ server bằng XMLHttpRequest hoặc Fetch API nhé!

Nhận phản hồi bằng XMLHttpRequest trong JavaScript

Đối tượng XMLHttpRequest là công cụ truyền thống trong JavaScript để thực hiện các yêu cầu HTTP đến server. Dù hiện nay Fetch API được sử dụng phổ biến hơn, XMLHttpRequest vẫn được dùng trong nhiều hệ thống cũ và có thể kiểm soát chi tiết quá trình gửi – nhận dữ liệu.

Tạo và gửi yêu cầu với XMLHttpRequest

Trước tiên, cần tạo đối tượng XMLHttpRequest và thiết lập yêu cầu:

const xhr = new XMLHttpRequest(); // Tạo đối tượng
xhr.open("GET", "https://api.example.com/data", true); // Cấu hình yêu cầu (GET, URL, bất đồng bộ)
xhr.send(); // Gửi yêu cầu

Các bước nhận phản hồi từ server

Sau khi gửi yêu cầu, trình duyệt sẽ lắng nghe và xử lý phản hồi khi server trả dữ liệu về. Có hai cách chính:

a. Sử dụng onreadystatechange
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log("Phản hồi từ server:", xhr.responseText);
  }
};

b. Hoặc sử dụng onload (cách viết gọn hơn)

xhr.onload = function () {
  if (xhr.status === 200) {
    console.log("Dữ liệu nhận được:", xhr.responseText);
  } else {
    console.error("Lỗi khi tải dữ liệu. Mã lỗi:", xhr.status);
  }
};

Lấy dữ liệu phản hồi

Dữ liệu phản hồi từ server có thể lấy thông qua các thuộc tính:

  • xhr.responseText: Trả về chuỗi văn bản (phổ biến với JSON, text).

  • xhr.responseXML: Trả về đối tượng XML (nếu server trả về định dạng XML).

Ví dụ minh họa: Nhận JSON và hiển thị kết quả

const xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/users", true);

xhr.onload = function () {
  if (xhr.status === 200) {
    const data = JSON.parse(xhr.responseText); // Chuyển đổi JSON thành object
    data.forEach(user => {
      console.log("Tên người dùng:", user.name);
    });
  } else {
    console.error("Lỗi khi lấy dữ liệu:", xhr.status);
  }
};

xhr.send();

Trong ví dụ trên, dữ liệu người dùng được lấy từ API và hiển thị trong console. Đây là bước đầu tiên quan trọng giúp ta xử lý và hiển thị thông tin nhận được từ server mà không cần reload trang.

Nhận phản hồi bằng Fetch API trong JavaScript

Fetch API là cách hiện đại và đơn giản hơn để thực hiện yêu cầu HTTP và nhận phản hồi từ server. Nó sử dụng Promise nên dễ đọc, dễ bảo trì và kết hợp tốt với async/await.

Gửi yêu cầu với fetch(url)

Cú pháp cơ bản để gửi yêu cầu GET đến một URL:

fetch("https://api.example.com/data")
  .then(response => {
    // Xử lý phản hồi ở đây
  });

Hàm fetch() trả về một Promise chứa một đối tượng Response, đại diện cho phản hồi từ server.

Sử dụng .then() để xử lý Response

Sau khi fetch() được thực hiện, ta thường dùng .then() để lấy dữ liệu từ Response:

fetch("https://api.example.com/data")
  .then(response => response.json()) // chuyển dữ liệu thành JSON
  .then(data => {
    // xử lý dữ liệu JSON ở đây
    console.log("Dữ liệu nhận được:", data);
  })
  .catch(error => {
    console.error("Lỗi khi fetch dữ liệu:", error);
  });

Các phương thức xử lý dữ liệu phản hồi

Fetch API cung cấp nhiều phương thức để chuyển đổi dữ liệu từ phản hồi:

  • .json() – Dùng khi server trả về JSON (dạng phổ biến nhất).

  • .text() – Dùng cho dữ liệu văn bản thuần túy.

  • .blob() – Dùng khi cần tải file hoặc dữ liệu nhị phân (ví dụ: ảnh, PDF).

  • .arrayBuffer() – Cho các xử lý cấp thấp như streaming media.

Ví dụ chuyển sang văn bản:

fetch("https://example.com/message.txt")
  .then(res => res.text())
  .then(text => console.log("Nội dung:", text));

Ví dụ minh họa: Lấy và hiển thị JSON từ API

fetch("https://jsonplaceholder.typicode.com/users")
  .then(response => {
    if (!response.ok) {
      throw new Error("Lỗi HTTP: " + response.status);
    }
    return response.json();
  })
  .then(data => {
    data.forEach(user => {
      console.log("Tên:", user.name);
    });
  })
  .catch(error => {
    console.error("Đã xảy ra lỗi:", error.message);
  });

Trong ví dụ này:

  • Gửi yêu cầu GET tới một API.

  • Kiểm tra phản hồi hợp lệ (response.ok).

  • Chuyển đổi và xử lý dữ liệu JSON.

  • Bắt và xử lý lỗi nếu có.

Fetch API giúp cho việc tương tác với server trong JavaScript trở nên dễ dàng và rõ ràng hơn rất nhiều so với XMLHttpRequest. Nếu bạn sử dụng async/await, đoạn mã còn gọn gàng hơn nữa!

Xử lý lỗi phản hồi trong JavaScript

Trong quá trình gửi và nhận dữ liệu từ server, có thể xảy ra nhiều loại lỗi. Việc xử lý lỗi giúp ứng dụng ổn định, nâng cao trải nghiệm người dùng và tránh sự cố khó kiểm soát.

Lỗi HTTP (404, 500,...)

Đây là lỗi phản hồi do server trả về, ví dụ:

  • 404: Không tìm thấy tài nguyên.

  • 500: Lỗi nội bộ phía server.

  • 403: Không có quyền truy cập.

Với Fetch API:

fetch("https://api.example.com/data")
  .then(response => {
    if (!response.ok) {
      throw new Error(`Lỗi HTTP: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    console.log("Dữ liệu:", data);
  })
  .catch(error => {
    console.error("Đã xảy ra lỗi:", error.message);
  });

Với XMLHttpRequest:

const xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data", true);

xhr.onload = function () {
  if (xhr.status === 200) {
    console.log("Dữ liệu:", xhr.responseText);
  } else {
    console.error("Lỗi HTTP:", xhr.status);
  }
};

xhr.send();

Lỗi kết nối mạng

Khi mất kết nối Internet hoặc server không phản hồi, bạn cần xử lý lỗi mạng.

Fetch API sử dụng .catch() để bắt các lỗi mạng:

fetch("https://api.example.com/data")
  .then(response => response.json())
  .catch(error => {
    console.error("Lỗi mạng hoặc không phản hồi:", error.message);
  });

XMLHttpRequest sử dụng onerror:

xhr.onerror = function () {
  console.error("Lỗi mạng hoặc không phản hồi từ server.");
};

Hiển thị thông báo lỗi cho người dùng

Thông báo lỗi giúp người dùng hiểu điều gì đang xảy ra. Ví dụ:

.catch(error => {
  document.getElementById("error-message").innerText =
    "Không thể tải dữ liệu. Vui lòng thử lại sau.";
});

4. Gợi ý thêm: Loading animation khi đang chờ phản hồi

Giúp người dùng biết hệ thống đang xử lý yêu cầu:

document.getElementById("loading").style.display = "block";

fetch("https://api.example.com/data")
  .then(response => response.json())
  .then(data => {
    // Xử lý dữ liệu
  })
  .finally(() => {
    document.getElementById("loading").style.display = "none";
  });

Các định dạng phản hồi phổ biến trong JavaScript

JSON (JavaScript Object Notation)

  • Là định dạng phổ biến nhất hiện nay.

  • Dễ đọc, nhẹ, dễ xử lý bằng JavaScript.

Ví dụ phản hồi JSON:

{
  "name": "Đậu Trung Kiên",
  "age": 5
}

Chuyển đổi JSON sang Object trong JS:

const jsonString = '{"name": "Đậu Trung Kiên", "age": 5}';
const obj = JSON.parse(jsonString);
console.log(obj.name); // "Đậu Trung Kiên"

Text (Plain Text)

  • Thường dùng cho dữ liệu đơn giản như thông báo, chuỗi trạng thái.

  • Dễ xử lý nhưng không có cấu trúc.

fetch("/status.txt")
  .then(res => res.text())
  .then(text => console.log("Trạng thái:", text));

XML

Được dùng phổ biến trong các hệ thống cũ, hoặc một số ứng dụng đặc biệt (SOAP).

  • Cần xử lý qua responseXML.

Ví dụ với XMLHttpRequest:

const xhr = new XMLHttpRequest();
xhr.open("GET", "data.xml", true);
xhr.onload = function () {
  const xml = xhr.responseXML;
  const items = xml.getElementsByTagName("item");
  console.log("Số lượng item:", items.length);
};
xhr.send();

Ứng dụng thực tế trong JavaScript

AJAX là công nghệ rất phổ biến và được ứng dụng rộng rãi trong các trang web hiện đại để tăng cường trải nghiệm người dùng mà không cần tải lại toàn bộ trang. Dưới đây là một số ứng dụng thực tế:

Hiển thị danh sách sản phẩm sau khi gọi API

Thay vì tải toàn bộ trang, trang web có thể chỉ gọi API và hiển thị dữ liệu sản phẩm mới:

fetch("/api/products")
  .then(res => res.json())
  .then(data => {
    const list = document.getElementById("product-list");
    list.innerHTML = data
      .map(
        product => `<li>${product.name} - ${product.price}₫</li>`
      )
      .join("");
  });

Ứng dụng: Website thương mại điện tử, quản lý kho, hiển thị hàng tồn kho…

Gợi ý tìm kiếm theo thời gian thực (Live Search)

Mỗi khi người dùng gõ phím, AJAX gửi từ khóa lên server và nhận lại danh sách gợi ý:

input.addEventListener("input", () => {
  fetch(`/api/search?q=${input.value}`)
    .then(res => res.json())
    .then(suggestions => {
      suggestionsBox.innerHTML = suggestions
        .map(item => `<div>${item}</div>`)
        .join("");
    });
});

Ứng dụng: Google Search, tìm kiếm sản phẩm, gợi ý tên người dùng...

Kiểm tra thông tin đăng nhập từ server

Sau khi người dùng nhập email/mật khẩu và nhấn đăng nhập, AJAX có thể gửi thông tin và nhận phản hồi:

fetch("/api/login", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ email, password }),
})
  .then(res => res.json())
  .then(data => {
    if (data.success) {
      alert("Đăng nhập thành công!");
    } else {
      alert("Sai tài khoản hoặc mật khẩu!");
    }
  });

Cập nhật thông báo, tin nhắn mới mà không cần reload

Thông qua polling hoặc WebSocket, AJAX có thể kiểm tra liên tục tin nhắn mới và hiển thị lên giao diện:

setInterval(() => {
  fetch("/api/notifications")
    .then(res => res.json())
    .then(data => {
      notificationBox.innerText = `Bạn có ${data.length} thông báo mới`;
    });
}, 5000); // Cập nhật mỗi 5 giây

Một số lưu ý quan trọng trong JavaScript

Dù AJAX rất mạnh mẽ và linh hoạt, việc sử dụng nó cần cẩn trọng để đảm bảo an toàn và hiệu quả.

Luôn kiểm tra lỗi phản hồi và xử lý phù hợp

Đừng bao giờ xử lý dữ liệu mà không kiểm tra xem server đã phản hồi thành công chưa:

  • Fetch: kiểm tra response.ok

  • XMLHttpRequest: kiểm tra xhr.status === 200

Đảm bảo định dạng phản hồi đúng như mong đợi

Nếu server trả về JSON nhưng bạn dùng .text() hoặc ngược lại, sẽ gây lỗi xử lý:

fetch("/api/data")
  .then(res => res.json()) // Phải chắc chắn server trả về JSON
  .catch(error => console.error("Lỗi khi phân tích JSON:", error));

Không nên xử lý dữ liệu khi chưa chắc chắn server trả về thành công

Cần chờ status hoặc ok xác nhận phản hồi hợp lệ rồi mới truy cập dữ liệu.

Cẩn thận với lỗi bảo mật và CORS

CORS (Cross-Origin Resource Sharing) là lỗi thường gặp khi gọi API từ domain khác:

  • Server phải thiết lập header Access-Control-Allow-Origin đúng cách.

  • Tránh gửi thông tin nhạy cảm như mật khẩu qua HTTP không bảo mật.

  • Kiểm tra kỹ server-side để ngăn tấn công XSS, CSRF khi dùng AJAX.

Tổng kết: AJAX và phản hồi từ server là phần cốt lõi trong phát triển web hiện đại. Nhưng bạn cần xử lý lỗi tốt, đảm bảo đúng định dạng dữ liệu, và bảo mật thông tin để hệ thống hoạt động trơn tru và an toàn.

Kết bài

AJAX đóng vai trò then chốt trong việc tạo ra các ứng dụng web hiện đại với trải nghiệm người dùng mượt mà và linh hoạt. Thay vì phải tải lại toàn bộ trang, AJAX cho phép nhận dữ liệu từ server một cách bất đồng bộ và cập nhật trực tiếp giao diện người dùng.

Việc nắm vững cách gửi yêu cầuxử lý phản hồi từ server thông qua XMLHttpRequest hoặc Fetch API sẽ giúp lập trình viên xây dựng những tính năng mạnh mẽ như tìm kiếm theo thời gian thực, gửi form không reload, cập nhật nội dung động, và hơn thế nữa.

Tuy nhiên, bên cạnh những tiện ích, lập trình viên cũng cần chú ý đến các vấn đề như xử lý lỗi, định dạng dữ liệu phản hồi, CORS, bảo mậttrạng thái mạng để đảm bảo ứng dụng hoạt động ổn định, bảo mật và thân thiện với người dùng.

Bài viết liên quan