Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Hàm bất đồng bộ (Async Functions) trong JavaScript

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ề Promise
  • await: 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 async luôn trả về Promise
  • await chỉ dùng được bên trong hàm async
  • Không dùng await ở top-level (trừ module: <script type="module">)
  • Tránh dùng await trong vòng lặp nếu có thể dùng Promise.all