0
0
Lập trình
Admin Team
Admin Teamtechmely

Hướng Dẫn Toàn Diện Về API Đồng Bộ và Không Đồng Bộ

Đăng vào 7 tháng trước

• 8 phút đọc

Chủ đề:

KungFuTech

Hướng Dẫn Toàn Diện Về API Đồng Bộ và Không Đồng Bộ

Khi xây dựng hoặc sử dụng API, việc hiểu rõ cách tiếp cận đồng bộ (sync) và không đồng bộ (async) là rất quan trọng để tạo ra các ứng dụng hiệu quả. Bài viết này sẽ đi sâu vào cả hai khái niệm với những ví dụ thực tiễn và các phương pháp tốt nhất.

🚦 API Đồng Bộ Là Gì?

API đồng bộ hoạt động giống như một cuộc trò chuyện truyền thống: bạn đặt câu hỏi, chờ đợi câu trả lời hoàn chỉnh và chỉ sau đó mới tiếp tục. Client gửi yêu cầu và bị chặn cho đến khi nhận được phản hồi.

Đặc Điểm Chính:

  • Yêu cầu → Chờ → Phản hồi → Tiếp tục
  • Luồng client bị chặn trong suốt quá trình hoạt động
  • Dễ hiểu và triển khai
  • Phản hồi ngay lập tức và trực tiếp

Phân Tích Thực Tế

Hãy tưởng tượng việc đặt món ăn tại một quán ăn vỉa hè—bạn phải chờ trong khi đầu bếp chuẩn bị món ăn của bạn.

Ví Dụ Mã Code

javascript Copy
// Cuộc gọi API đồng bộ
async function getUserData(userId) {
    console.log("Đang yêu cầu dữ liệu người dùng...");

    const response = await fetch(`/api/users/${userId}`);
    const userData = await response.json();

    console.log("Đã nhận dữ liệu người dùng:", userData);
    return userData;
}

// Mọi thứ chờ hoàn thành
const user = await getUserData(123);
console.log("Đang xử lý người dùng:", user.name);

⚡ API Không Đồng Bộ Là Gì?

API không đồng bộ giống như việc gửi tin nhắn. Bạn gửi yêu cầu, tiếp tục làm việc khác và phản hồi sẽ đến sau đó thông qua callback hoặc webhook.

Đặc Điểm Chính:

  • Yêu cầu → Tiếp tục làm việc → Nhận phản hồi sau
  • Hoạt động không chặn
  • Tối ưu hóa việc sử dụng tài nguyên
  • Xử lý các tác vụ lâu dài một cách hiệu quả

Phân Tích Thực Tế

Giống như việc đặt món tại một nhà hàng—bạn đặt hàng, nhận biên nhận, sau đó thư giãn cho đến khi người phục vụ mang món ăn đến.

Ví Dụ Mã Code

javascript Copy
// API không đồng bộ với callback
function processLargeFile(fileId, callback) {
    console.log("Bắt đầu xử lý tệp...");

    // Khởi động xử lý
    fetch('/api/files/process', {
        method: 'POST',
        body: JSON.stringify({ fileId })
    })
    .then(response => response.json())
    .then(data => {
        console.log("Đã bắt đầu xử lý, ID công việc:", data.jobId);

        // Tiếp tục với công việc khác
        doOtherWork();

        // Kiểm tra trạng thái sau hoặc chờ webhook
        checkProcessingStatus(data.jobId, callback);
    });
}

🔍 Sự Khác Biệt Chính

Tính Năng API Đồng Bộ API Không Đồng Bộ
Thời Gian Phản Hồi Ngay lập tức Trễ/Callback
Khóa Client Có, chờ phản hồi Không, tiếp tục xử lý
Sử Dụng Tài Nguyên Cao (luồng bị khóa) Thấp (không chặn)
Độ Phức Tạp Dễ triển khai Phức tạp hơn trong xử lý
Khả Năng Mở Rộng Hạn chế bởi việc chặn Rất dễ mở rộng
Tình Huống Sử Dụng Các thao tác nhanh Các tác vụ lâu dài, tính đồng thời cao

🛠 Ví Dụ Thực Tế

API Đồng Bộ ✅

  • Xác thực: Xác thực đăng nhập cần phản hồi ngay lập tức
  • Lấy Dữ Liệu: Hồ sơ người dùng để hiển thị UI
  • Xác Thực Thời Gian Thực: Kiểm tra tính khả dụng email, các trường trong biểu mẫu
  • API Thời Tiết: Dữ liệu nhiệt độ hiện tại
  • Chuyển Đổi Tiền Tệ: Tỷ giá hối đoái trực tiếp

API Không Đồng Bộ ⚡

  • Xử Lý Tệp: Tải video lên, xử lý hình ảnh
  • Xử Lý Thanh Toán: Tính phí thẻ tín dụng, chuyển khoản ngân hàng
  • Dịch Vụ Email: Chiến dịch email hàng loạt
  • AWS S3: Tải lên tệp lớn với theo dõi tiến trình
  • Tích Hợp Bên Thứ Ba: Đồng bộ CRM, cập nhật tồn kho

🏗 Mô Hình Triển Khai

Mô Hình Webhook

javascript Copy
// Bắt đầu xử lý không đồng bộ
async function processPayment(paymentData) {
    const response = await fetch('/api/payments/initiate', {
        method: 'POST',
        body: JSON.stringify(paymentData)
    });

    const { transactionId } = await response.json();

    // Webhook sẽ thông báo khi hoàn thành
    return {
        transactionId,
        message: "Đang xử lý thanh toán",
        statusUrl: `/api/payments/${transactionId}/status`
    };
}

// Bộ xử lý webhook
app.post('/webhooks/payment-status', (req, res) => {
    const { transactionId, status } = req.body;

    // Cập nhật cơ sở dữ liệu và thông báo cho người dùng
    updatePaymentStatus(transactionId, status);
    notifyUser(transactionId, status);

    res.json({ received: true });
});

Mô Hình Polling

javascript Copy
async function pollForResult(jobId) {
    let completed = false;

    while (!completed) {
        const status = await fetch(`/api/jobs/${jobId}/status`);
        const data = await status.json();

        if (data.status === 'completed') {
            return data.result;
        }

        // Chờ trước khi kiểm tra lần tiếp theo
        await new Promise(resolve => setTimeout(resolve, 5000));
    }
}

⚠️ Cạm Bẫy Thông Thường & Giải Pháp

Vấn Đề Đồng Bộ

Vấn Đề: Lỗi timeout trong các tác vụ lâu dài

javascript Copy
// ❌ Xấu - có thể hết thời gian
const report = await heavyReportGeneration(params);

// ✅ Tốt - chuyển sang không đồng bộ
const job = await initiateReportGeneration(params);
return { jobId: job.id, statusUrl: `/api/reports/status/${job.id}` };

Vấn Đề Không Đồng Bộ

Vấn Đề: Mất yêu cầu mà không có xử lý lỗi hợp lý

javascript Copy
// ❌ Xấu - không có phương thức dự phòng nếu webhook thất bại
initiatePayment(paymentData);

// ✅ Tốt - nhiều phương thức thông báo
const result = await initiatePayment(paymentData);
setupWebhookHandler(result.transactionId);
setTimeout(() => pollPaymentStatus(result.transactionId), 30000);

🎯 Khi Nào Nên Sử Dụng Cái Gì?

Chọn API Đồng Bộ Khi:

  • Các thao tác hoàn tất trong < 5 giây
  • Các thao tác CRUD đơn giản
  • Dữ liệu thời gian thực cần cho quyết định ngay lập tức
  • Client phải chờ kết quả để tiếp tục
  • Quy trình yêu cầu-phản hồi đơn giản

Ví dụ: Đăng nhập, xác thực biểu mẫu, lấy tùy chọn dropdown

Chọn API Không Đồng Bộ Khi:

  • Các thao tác mất > 10 giây
  • Tác vụ tốn tài nguyên
  • Tình huống có độ đồng thời cao
  • Phụ thuộc vào API bên thứ ba
  • Tác vụ hàng loạt

Ví dụ: Xử lý video, xử lý thanh toán, xuất dữ liệu

Phương Pháp Kết Hợp

javascript Copy
async function submitOrder(orderData) {
    // 1. Xác thực nhanh (đồng bộ)
    const validation = await validateOrderData(orderData);
    if (!validation.valid) {
        return { error: validation.errors };
    }

    // 2. Bắt đầu xử lý không đồng bộ
    const jobId = await initiateOrderProcessing(orderData);

    // 3. Trả về phản hồi ngay lập tức
    return {
        success: true,
        orderId: orderData.id,
        jobId,
        message: "Đơn hàng đã nhận và đang được xử lý",
        trackingUrl: `/api/orders/${orderData.id}/status`
    };
}

🚀 Các Thực Hành Tốt Nhất

API Đồng Bộ

  • Triển khai timeout để ngăn chặn các yêu cầu treo
  • Sử dụng caching cho dữ liệu thường xuyên được yêu cầu
  • Tối ưu hóa truy vấn cơ sở dữ liệu để có phản hồi nhanh hơn

API Không Đồng Bộ

  • Triển khai các cơ chế thử lại cho các webhook thất bại
  • Cung cấp hệ thống theo dõi trạng thái
  • Sử dụng giới hạn tốc độ để ngăn chặn quá tải hệ thống
  • Luôn có phương thức thông báo dự phòng

🎯 Những Điểm Quan Trọng

Hướng Dẫn Quyết Định Nhanh:

Chọn Đồng Bộ khi bạn cần:

  • Kết quả ngay lập tức
  • Các thao tác đơn giản
  • Quy trình yêu cầu-phản hồi trực tiếp

Chọn Không Đồng Bộ khi bạn có:

  • Các thao tác lâu dài
  • Yêu cầu khả năng mở rộng cao
  • Tác vụ tốn tài nguyên

Quy Tắc Vàng:

  1. Đồng Bộ = Chờ câu trả lời 🔄
  2. Không Đồng Bộ = Gửi và tiếp tục, câu trả lời sẽ đến sau
  3. Khớp mô hình với trường hợp sử dụng của bạn 🎯
  4. Luôn triển khai xử lý lỗi hợp lý ⚠️

🏁 Kết Luận

Hiểu rõ sự khác biệt giữa API đồng bộ và không đồng bộ là rất quan trọng để xây dựng các ứng dụng hiệu quả. API đồng bộ rất phù hợp cho các thao tác nhanh, tức thời, trong khi API không đồng bộ nổi bật với các tác vụ lâu dài và khả năng phản hồi của hệ thống.

Lần tới khi bạn làm việc với thanh toán Stripe, xử lý tệp AWS, hoặc dịch vụ email, hãy đặt câu hỏi cho chính mình:

🤔 Tôi có cần đợi kết quả hoàn chỉnh không, hay tôi có thể để nó xử lý trong nền?

Câu trả lời sẽ hướng dẫn bạn đến quyết định kiến trúc đúng đắn.


Tags cho Dev.to

Copy
#api #javascript #webdev #backend #async #programming
Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào