Khái niệm
Async/Await (ES2017) là cú pháp đường cú pháp (syntactic sugar) trên Promise, giúp viết code bất đồng bộ trông như đồng bộ, dễ đọc và dễ xử lý lỗi hơn.
async: Từ khóa khai báo hàm bất đồng bộ, luôn trả về Promiseawait: Tạm dừng hàm cho đến khi Promise resolve, chỉ dùng trong hàm async
Ví dụ cơ bản
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Async Functions</title>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px; }
.result { font-size: 18px; color: #6a1b9a; font-weight: 500; margin: 20px 0; padding: 15px; background: #f3e5f5; border-radius: 4px; min-height: 50px; }
button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
button:disabled { background: #90caf9; cursor: not-allowed; }
</style>
</head>
<body>
<h1>Hàm bất đồng bộ trong JavaScript</h1>
<div class="result" id="result">Nhấn nút để bắt đầu...</div>
<button id="btn">GỌI HÀM ASYNC</button>
<h3>Nhấn nút để gọi hàm asyncFunc</h3>
<script>
const btnEle = document.getElementById('btn');
const resEle = document.getElementById('result');
// Hàm trả về Promise (giả lập API call)
function displayText() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Hello World từ Promise!');
}, 1500);
});
}
// Hàm async sử dụng await
async function asyncFunc() {
btnEle.disabled = true;
btnEle.textContent = 'Đang tải...';
resEle.innerHTML = 'Đang chờ Promise...';
try {
const message = await displayText();
resEle.innerHTML = `✅ ${message}`;
} catch (error) {
resEle.innerHTML = `❌ Lỗi: ${error.message}`;
} finally {
btnEle.disabled = false;
btnEle.textContent = 'GỌI HÀM ASYNC';
}
}
btnEle.addEventListener('click', asyncFunc);
</script>
</body>
</html>
Kết quả
Nhấn nút → hiển thị "Đang chờ Promise..." → sau 1.5 giây hiển thị "✅ Hello World từ Promise!"
Xử lý nhiều Promise song song
// Tuần tự (chậm hơn)
const user = await fetchUser(id);
const posts = await fetchPosts(id);
// Song song (nhanh hơn) - Promise.all
const [user, posts] = await Promise.all([
fetchUser(id),
fetchPosts(id)
]);
// Promise.allSettled - không fail fast
const results = await Promise.allSettled(promises);
results.forEach((r, i) => {
if (r.status === 'fulfilled') console.log(i, r.value);
else console.log(i, r.reason);
});
Xử lý lỗi (Error Handling)
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
return data;
} catch (error) {
console.error('Lỗi:', error);
throw error; // Ném lại hoặc xử lý
}
}
Lưu ý quan trọng
- Hàm
asyncluôn trả vềPromise awaitchỉ dùng được bên trong hàmasync- Không dùng
awaitở top-level (trừ module:<script type="module">) - Tránh dùng
awaittrong vòng lặp nếu có thể dùngPromise.all