Async Await
Bài 12 – Hiểu cơ chế bất đồng bộ và cách dùng async/await để viết code rõ ràng, dễ đọc và tránh callback hell.
Async/Await
Async/Await giúp viết code bất đồng bộ (asynchronous) rõ ràng, dễ đọc như code đồng bộ.
Đây là công cụ quan trọng nhất khi làm việc với Fetch API, xử lý dữ liệu, gọi API liên tục và xây dựng flow nghiệp vụ.
Tư duy cốt lõi:
“async/await = viết code bất đồng bộ như đồng bộ.”
1. Bất đồng bộ là gì?
JavaScript chạy đơn luồng, nhưng cần xử lý các tác vụ mất thời gian như:
- gọi API
- đọc file
- đợi server phản hồi
Để không chặn giao diện, JavaScript dùng bất đồng bộ.
Ví dụ: Fetch API không đợi server mà trả về Promise.
2. Promise – nền tảng của async/await (hiểu ngắn gọn)
Phần lớn async/await hoạt động dựa trên Promise.
Ví dụ Promise:
let p = new Promise(resolve => {
setTimeout(() => resolve("Done"), 1000);
});
Sử dụng Promise:
p.then(result => console.log(result));
3. async/await là gì?
async
Đánh dấu một hàm là bất đồng bộ và luôn trả về Promise.
await
Tạm dừng code trong hàm async cho đến khi Promise hoàn thành.
4. Ví dụ cơ bản nhất
async function run() {
let result = await Promise.resolve(10);
console.log(result);
}
run();
5. Dùng async/await với Fetch API
Cách viết bằng .then:
fetch(url)
.then(res => res.json())
.then(data => console.log(data));
Viết lại bằng async/await:
async function loadData() {
let res = await fetch(url);
let data = await res.json();
console.log(data);
}
Dễ đọc – rõ ràng – logic tuần tự.
6. Xử lý lỗi với try/catch (rất quan trọng)
async function loadData() {
try {
let res = await fetch(url);
if (!res.ok) {
throw new Error("Lỗi server: " + res.status);
}
let data = await res.json();
console.log(data);
} catch (error) {
console.error("Fetch lỗi:", error);
}
}
try/catch giúp tránh crash khi call API lỗi.
7. Chạy nhiều request song song (tối ưu hiệu suất)
Đôi khi cần gọi nhiều API → dùng Promise.all
async function loadAll() {
let [users, posts] = await Promise.all([
fetch("https://jsonplaceholder.typicode.com/users").then(r => r.json()),
fetch("https://jsonplaceholder.typicode.com/posts").then(r => r.json())
]);
console.log(users, posts);
}
Nhanh gấp đôi so với gọi tuần tự.
8. Tạm dừng chương trình có kiểm soát (delay)
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
console.log("Bắt đầu");
await sleep(1000);
console.log("1 giây sau…");
}
9. Sai lầm thường gặp
- Quên dùng await → biến nhận Promise thay vì dữ liệu
- Quên đặt hàm là async → await không hoạt động
- Lạm dụng await trong vòng lặp → chậm (nên dùng Promise.all)
- Không dùng try/catch → chương trình dễ lỗi khi API sai
- Vừa await vừa .then → code rối
10. Bài tập thực hành
Bài 1
Gọi API users bằng async/await và in ra danh sách tên.
Bài 2
Tạo hàm getPost(id) dùng async/await để lấy bài viết theo id.
Bài 3
Tạo hàm gọi 2 API song song bằng Promise.all:
- posts
- comments
In kết quả ra console.
Bài 4
Tạo hàm delay(ms) và viết demo chạy:
Bắt đầu
(đợi 2 giây)
Hoàn thành
11. Kết luận bài học
- async/await giúp code bất đồng bộ dễ đọc và rõ ràng
- Dùng await để xử lý Promise theo dạng tuần tự
- Dùng try/catch để tránh lỗi crash
- Promise.all giúp tăng hiệu suất khi gọi API song song