Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Hầu hết ứng dụng web hiện đại đều lấy dữ liệu từ API thay vì viết cứng vào trang. Trong bài này, bạn sẽ dùng fetch và async/await để tải danh sách bài viết từ một API thử nghiệm công khai, hiển thị lên trang, và xử lý các trạng thái đang tải, lỗi, rỗng.
API là "cửa giao tiếp" để chương trình này lấy dữ liệu từ chương trình khác, thường qua giao thức HTTP và trả về định dạng JSON. Hàm fetch có sẵn trong trình duyệt gửi yêu cầu HTTP và trả về một Promise. Bạn dùng await để chờ kết quả mà không chặn giao diện.
Để thực hành, ta dùng dịch vụ thử nghiệm JSONPlaceholder, cung cấp dữ liệu giả miễn phí tại địa chỉ https://jsonplaceholder.typicode.com/posts. Dịch vụ này chỉ dành cho học tập và thử nghiệm.
<main class="container">
<h1>Bài viết mới</h1>
<input id="search" type="search" placeholder="Tìm theo tiêu đề...">
<p id="status" role="status"></p>
<ul id="posts"></ul>
</main>
<script src="app.js"></script>Điều quan trọng nhất: fetch chỉ báo lỗi (reject) khi mạng hỏng, không báo lỗi khi máy chủ trả 404 hay 500. Vì vậy bạn phải tự kiểm tra response.ok.
const API_URL = 'https://jsonplaceholder.typicode.com/posts?_limit=20';
async function fetchPosts() {
const response = await fetch(API_URL);
if (!response.ok) {
throw new Error('Máy chủ trả về lỗi ' + response.status);
}
return response.json();
}Một giao diện tử tế cần xử lý ít nhất bốn trạng thái: đang tải, có dữ liệu, không có kết quả, và lỗi. Đây là phần nhiều người mới bỏ qua.
const statusEl = document.getElementById('status');
const listEl = document.getElementById('posts');
const searchEl = document.getElementById('search');
let allPosts = [];
function render(posts) {
listEl.innerHTML = '';
if (posts.length === 0) {
statusEl.textContent = 'Không tìm thấy bài viết nào.';
return;
}
statusEl.textContent = '';
const fragment = document.createDocumentFragment();
posts.forEach((post) => {
const li = document.createElement('li');
const title = document.createElement('h2');
const body = document.createElement('p');
title.textContent = post.title;
body.textContent = post.body;
li.append(title, body);
fragment.appendChild(li);
});
listEl.appendChild(fragment);
}
async function init() {
statusEl.textContent = 'Đang tải...';
try {
allPosts = await fetchPosts();
render(allPosts);
} catch (error) {
statusEl.textContent = 'Không tải được dữ liệu. Vui lòng thử lại.';
console.error(error);
}
}
searchEl.addEventListener('input', () => {
const keyword = searchEl.value.trim().toLowerCase();
const filtered = allPosts.filter((p) =>
p.title.toLowerCase().includes(keyword)
);
render(filtered);
});
init();Ta dùng textContent để gán nội dung từ API, tránh nguy cơ chèn mã độc nếu dữ liệu không đáng tin. DocumentFragment giúp thêm nhiều phần tử vào trang chỉ với một lần cập nhật DOM, hiệu quả hơn thêm từng phần tử một.
Ngoài việc lấy dữ liệu, bạn có thể gửi dữ liệu mới. Cần khai báo phương thức, tiêu đề loại nội dung và thân yêu cầu dạng chuỗi JSON:
async function createPost(title, body) {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, body, userId: 1 }),
});
if (!response.ok) throw new Error('Gửi thất bại');
return response.json();
}API thử nghiệm sẽ giả lập việc tạo bản ghi và trả về dữ liệu kèm một mã định danh, nhưng không thật sự lưu lại.
await cả fetch lẫn response.json().try/catch và hiển thị thông báo thân thiện._page và _limit.AbortController để hủy yêu cầu cũ khi người dùng gõ tìm kiếm nhanh.sessionStorage để tránh gọi lại.Gọi API là kỹ năng nền tảng của lập trình web. Hãy nhớ ba điều: kiểm tra response.ok, xử lý lỗi bằng try/catch, và luôn thiết kế đủ các trạng thái của giao diện. Có nền tảng này, bạn có thể kết nối với hầu hết dịch vụ dữ liệu khác.
Để học cách xây dựng cả phần giao diện lẫn API, bạn có thể xem các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment