Mục lục
Promise là gì?
- Một giá trị đại diện cho kết quả trong tương lai, có 3 trạng thái:
pending,fulfilled,rejected. - Xử lý kết quả bằng
.then(), lỗi bằng.catch(), dọn dẹp bằng.finally().
fetch('/api/user')
.then(r => r.json())
.then(data => console.log('User', data))
.catch(err => console.error(err))
.finally(() => console.log('done'));
async/await là gì?
- Hàm khai báo
asyncluôn trả vềPromise. await“tạm dừng” trong phạm vi hàm async cho đến khi Promise hoàn thành (không chặn event loop).
async function loadUser() {
try {
const r = await fetch('/api/user');
const data = await r.json();
console.log('User', data);
} catch (err) {
console.error(err);
} finally {
console.log('done');
}
}
So sánh nhanh
| Tiêu chí | Promise | async/await |
|---|---|---|
| Độ dễ đọc | Dễ tạo “callback chain” dài | Gần như code đồng bộ, dễ đọc |
| Xử lý lỗi | .catch() cuối chuỗi |
try/catch theo block |
| Song song | Dùng Promise.all thuận tiện |
Dùng Promise.all (đừng await trong vòng lặp) |
| API tổng hợp | all, allSettled, race, any |
Vẫn dùng các API Promise |
| Tương thích | Rộng rãi | Hiện đại, đã hỗ trợ tốt (kể cả top‑level await trong môi trường hỗ trợ module) |
Xử lý lỗi: .catch vs try/catch
// Promise
getUser().then(saveUser).catch(handleError);
// async/await
try {
const u = await getUser();
await saveUser(u);
} catch (e) {
handleError(e);
}
Tuần tự vs Song song: tránh await trong vòng lặp
// (KHÔNG NÊN) tuần tự chậm
for (const url of urls) {
const r = await fetch(url); // đợi từng cái
results.push(await r.json());
}
// (NÊN) song song nhanh hơn
const promises = urls.map(u => fetch(u).then(r => r.json()));
const results = await Promise.all(promises);
Các API Promise hữu ích
Promise.all([p1, p2]): thất bại nếu bất kỳ promise nào fail; nhanh cho tác vụ bắt buộc đủ.Promise.allSettled([p1, p2]): luôn trả kết quả cho tất cả, hữu ích khi không muốn fail cả lô.Promise.race([p1, p2]): trả kết quả/lỗi của promise hoàn thành đầu tiên.Promise.any([p1, p2]): trả kết quả đầu tiên thành công; chỉ fail nếu tất cả đều fail.
Chuyển từ Promise chain sang async/await
// Promise chain
login()
.then(getProfile)
.then(render)
.catch(showError);
// async/await
try {
const session = await login();
const profile = await getProfile(session);
render(profile);
} catch (e) {
showError(e);
}
Thực hành tốt
- Tách khởi tạo promise và await để chạy song song khi có thể.
- Dùng
try/catchở ranh giới (controller/handler); để hàm dưới ném lỗi lên trên. - Với tác vụ độc lập:
Promise.allhoặcallSettled. - Tránh mix lẫn
.thenvàawaittrong cùng một flow trừ khi thật cần thiết. - Top‑level await: dùng trong module ES (
<script type="module">) hoặc bundler hiện đại.
Demo trực quan (chạy ngay tại đây)
Kết luận
Nếu muốn dễ đọc và điều khiển luồng theo khối, hãy dùng async/await. Khi cần song song hoặc thao tác với nhiều promise một lúc, hãy tận dụng các API của Promise như all / allSettled. Nhớ rằng async/await không thay thế Promise — chúng bổ trợ cho nhau.
Bình luận