Siêu Năng Lực Bất Đồng Bộ của JavaScript: Event Loop & Promises
Lê Lân
0
JavaScript’s Async Superpower: Vòng Lặp Sự Kiện và Promise
Mở Đầu
Bạn đã bao giờ đặt món ăn tại nhà hàng và tự hỏi làm sao bếp có thể xử lý nhiều đơn hàng cùng lúc chưa? JavaScript cũng hoạt động tương tự như người bếp ấy — theo cách cực kỳ hiệu quả và linh hoạt.
Trong thế giới lập trình web, khả năng xử lý các tác vụ bất đồng bộ (asynchronous) mà không làm chậm trải nghiệm người dùng là điều rất quan trọng. JavaScript là ngôn ngữ đơn luồng (single-threaded) nhưng vẫn làm tốt việc này nhờ vòng lặp sự kiện (event loop) và Promises. Bài viết này sẽ giúp bạn hiểu rõ cách thức hoạt động của chúng, từ đó lập trình hiệu quả hơn với async trong JavaScript.
Bạn sẽ được khám phá:
Vòng lặp sự kiện trong JavaScript là gì và hoạt động ra sao.
Cách Promises giải quyết vấn đề "callback hell".
Cách sử dụng và chuỗi hóa (chaining) Promise.
Các phương thức Promise tiện dụng khi làm việc với nhiều async task cùng lúc.
Vòng Lặp Sự Kiện Trong JavaScript Là Gì?
JavaScript chạy trên một luồng duy nhất, nghĩa là nó chỉ thực thi từng đoạn code lần lượt tại một thời điểm. Tuy nhiên, nhờ vòng lặp sự kiện, JavaScript vẫn có thể xử lý nhiều tác vụ một cách linh hoạt và hiệu quả.
Hiểu Vòng Lặp Sự Kiện Qua Ví Dụ
Giống như đầu bếp chuẩn bị món ăn từng bước một nhưng không ngồi đợi món trước chín hẳn mới làm món tiếp theo. Khi lò nướng đang làm bánh pizza, đầu bếp sẽ tranh thủ xử lý món khác. Vòng lặp sự kiện giúp JavaScript tương tự như vậy trong xử lý các tác vụ đồng thời.
🚦 Cách Thức Hoạt Động Của Vòng Lặp Sự Kiện
Các Thành Phần Cốt Lõi
Call Stack (Ngăn xếp lời gọi)
Thực thi mã đồng bộ theo thứ tự, chạy từng lệnh một.
Web APIs (Xử lý bất đồng bộ)
Các API như setTimeout, fetch, sự kiện người dùng được thực hiện bên ngoài call stack.
Callback Queue (Hàng đợi Macrotask)
Khi async task hoàn thành, callback được đẩy vào hàng đợi này.
Microtask Queue (Ưu tiên cao hơn)
Bao gồm callbacks của Promises, được xử lý trước macrotasks.
Event Loop
Liên tục kiểm tra call stack; nếu rỗng, lấy callback từ microtask queue rồi đến macrotask queue để chạy.
Minh Họa Bằng Mã Nguồn
console.log('Start');
setTimeout(() => {
console.log('Timeout Callback');
}, 0);
Promise.resolve().then(() => {
console.log('Promise Callback');
});
console.log('End');
Dự Kiến Kết Quả
Start
End
Promise Callback
Timeout Callback
Điều quan trọng là Microtask Queue (Promise) luôn được thực thi trước Macrotask Queue (setTimeout) dù thời gian setTimeout là 0ms.
Promise Trong JavaScript: Hoạt Động và Ý Nghĩa
Từ Callback Hell đến Promises
Trước khi Promises xuất hiện, việc xử lý các tác vụ async thường dùng callbacks, dẫn đến code khó đọc và bảo trì — còn gọi là callback hell.