Nhiều việc mất thời gian như tải dữ liệu từ mạng. JavaScript xử lý chúng bằng Promise và async/await mà không làm đơ trang.
- Hiểu bất đồng bộ là gì
- Dùng Promise và async/await
- Gọi API bằng fetch
- Xử lý lỗi mạng
- Bất đồng bộ
- Việc chạy ngầm, kết quả có sau, chương trình không phải chờ.
- Promise
- Đối tượng đại diện kết quả sẽ có trong tương lai: đang chờ, thành công, hoặc lỗi.
- API
- Địa chỉ cung cấp dữ liệu cho chương trình khác dùng.
- async/await
- Cú pháp viết mã bất đồng bộ trông như mã tuần tự.
Khái niệm và lý thuyết
JavaScript chỉ có một luồng thực thi, nghĩa là tại một thời điểm chỉ làm một việc. Nếu chờ mạng 3 giây trong luồng chính thì trang đơ. Giải pháp là bất đồng bộ: giao việc chậm cho trình duyệt, tiếp tục chạy mã khác, khi có kết quả thì đưa hàm xử lý vào hàng đợi để vòng lặp sự kiện (event loop) chạy khi luồng rảnh.
Có ba cách viết bất đồng bộ theo thời gian: callback (dễ lồng nhau thành "địa ngục callback"), Promise (đối tượng đại diện kết quả tương lai với ba trạng thái: pending, fulfilled, rejected) và async/await (cú pháp đẹp trên nền Promise). await chỉ tạm dừng hàm async đó, không chặn cả chương trình.
API HTTP: mỗi yêu cầu có phương thức (GET lấy dữ liệu, POST gửi dữ liệu), địa chỉ, và phản hồi có mã trạng thái (200 thành công, 404 không thấy, 500 lỗi máy chủ). Hàm fetch trả về Promise.
Vì sao cần bất đồng bộ?
Nếu tải ảnh mất 3 giây mà trang phải đứng chờ thì rất khó chịu. Trình duyệt giao việc đó cho nền, khi xong sẽ báo cho mã của bạn.
fetch và async/await
async function layBaiViet() {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/posts/1");
if (!res.ok) throw new Error("Lỗi " + res.status);
const data = await res.json();
console.log(data.title);
} catch (loi) {
console.error("Không tải được:", loi.message);
}
}
layBaiViet();Ví dụ: lấy dữ liệu từ một API công khai
async function layViecCanLam() {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/todos/1");
const data = await res.json();
console.log(data.title);
} catch (loi) {
console.log("Không tải được:", loi);
}
}
layViecCanLam();Trang JSONPlaceholder cung cấp dữ liệu mẫu miễn phí để bạn luyện tập mà không cần tự dựng máy chủ. Hãy luôn bọc try/catch khi gọi mạng vì kết nối có thể thất bại bất cứ lúc nào.
Promise nhiều việc cùng lúc
const [a, b] = await Promise.all([
fetch("/api/a").then(r => r.json()),
fetch("/api/b").then(r => r.json())
]);Chạy song song nhanh hơn chờ từng việc xong mới làm việc kế tiếp.
Gọi API thời tiết, hiện nhiệt độ lên trang và báo lỗi khi mất mạng. Mô hình: fetch → json() → gắn vào DOM → catch báo lỗi.
Luôn kiểm tra res.ok vì fetch chỉ báo lỗi khi mất mạng, không báo khi máy chủ trả 404 hoặc 500.
Quên await sẽ nhận về Promise chứ không phải dữ liệu.
- Gọi API công khai và in 5 bài viết đầu tiên lên trang.
- Thêm thông báo "Đang tải..." trước khi có dữ liệu.
- Thử ngắt mạng để xem khối catch hoạt động.
- Bất đồng bộ giữ cho trang không bị đơ.
async/awaitlàm mã dễ đọc.fetchcần kiểm trares.okvà bọctry/catch.