Vòng Lặp Sự Kiện trong JavaScript: Giải Thích Chi Tiết và Dễ Hiểu
JavaScript là một trong những ngôn ngữ lập trình phổ biến nhất, chiếm tới 90% số lượng website trên toàn thế giới. Tuy nhiên, bên trong ngôn ngữ này lại tiềm ẩn một khái niệm phức tạp mà nhiều lập trình viên thường xuyên hiểu sai: vòng lặp sự kiện (event loop). Bài viết này sẽ giúp bạn hiểu rõ hơn về vòng lặp sự kiện, hàng đợi tác vụ, ngăn xếp cuộc gọi, hàng đợi tác vụ vi mô và Web API.
1. Web API là gì?
Web API là những công cụ bổ sung được cung cấp bởi trình duyệt hoặc Node.js, giúp xử lý các tác vụ như:
- Gửi yêu cầu mạng (sử dụng fetch).
- Đặt hẹn giờ (setTimeout).
- Truy cập vị trí người dùng (thông qua Geolocation API).
Các tác vụ này hoạt động độc lập bên ngoài luồng JavaScript chính. Ví dụ, đoạn mã sau sẽ in ra dòng chữ "Timer done!" sau 2 giây, trong khi luồng JavaScript chính vẫn tiếp tục thực thi các đoạn mã khác:
javascript
setTimeout(() => {
console.log("Timer done!");
}, 2000);
2. Hàng Đợi Tác Vụ là gì?
Hàng đợi tác vụ (Task Queue) là nơi lưu trữ các hàm callback từ Web API, event listener, và các hành động trì hoãn khác đang chờ đến lượt để được JavaScript xử lý. Bạn có thể tưởng tượng hàng đợi tác vụ giống như một hàng dài người đứng chờ tại cửa hàng. Mỗi tác vụ sẽ được xử lý bởi vòng lặp sự kiện ngay khi JavaScript hoàn thành tác vụ hiện tại.
3. Ngăn Xếp Cuộc Gọi là gì?
Ngược lại, ngăn xếp cuộc gọi (Call Stack) là nơi mà JavaScript theo dõi các lời gọi hàm. Khi một hàm được gọi, nó sẽ được đưa vào ngăn xếp. Khi hàm hoàn tất, nó sẽ được loại bỏ ra khỏi ngăn xếp. JavaScript xử lý các tác vụ dựa trên thứ tự xuất hiện trong ngăn xếp, thể hiện tính chất đồng bộ của nó.
4. Vòng Lặp Sự Kiện là gì?
Vòng lặp sự kiện (Event Loop) hoạt động như một "người điều phối giao thông", đảm bảo rằng mọi thứ được thực hiện một cách suôn sẻ. Nó liên tục kiểm tra xem ngăn xếp cuộc gọi có trống hay không. Nếu trống, nó sẽ chuyển các tác vụ từ hàng đợi tác vụ hoặc hàng đợi tác vụ vi mô vào ngăn xếp để thực thi.
Để hiểu rõ hơn về cách thức hoạt động của vòng lặp sự kiện, hãy phân tích đoạn mã sau:
javascript
setTimeout(() => {
console.log("2000ms");
}, 2000);
setTimeout(() => {
console.log("100ms");
}, 100);
console.log("End");
Ở đây, "End" sẽ được in ra ngay lập tức vì nó là mã đồng bộ và đang chạy trong ngăn xếp cuộc gọi. Sau đó, setTimeout với 100ms sẽ được xử lý bởi Web API. Sau 100ms, hàm callback của nó sẽ được chuyển vào hàng đợi tác vụ. Tương tự, setTimeout với 2000ms cũng sẽ được xử lý và chuyển vào hàng đợi tác vụ sau 2000ms. Vòng lặp sự kiện sau đó sẽ thực thi hàm callback của setTimeout 100ms trước, sau đó mới đến hàm callback 2000ms.
5. Hàng Đợi Tác Vụ Vi Mô là gì?
Hàng đợi tác vụ vi mô (Microtask Queue) là một hàng đợi đặc biệt dành cho các tác vụ cần được xử lý trước hàng đợi tác vụ thông thường. Các tác vụ vi mô thường đến từ các đối tượng như Promises hoặc mutation observer. Vòng lặp sự kiện sẽ luôn kiểm tra hàng đợi tác vụ vi mô trước hàng đợi tác vụ.
Dưới đây là ví dụ minh họa cho cách thức hoạt động của hàng đợi tác vụ vi mô với Promise:
javascript
console.log("Start");
setTimeout(() => {
console.log("Timeout");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("End");
Ở đây, "Start" sẽ được in ra trước tiên. Sau đó, hàm callback của setTimeout sẽ được đưa vào hàng đợi tác vụ, và Promise sẽ được đưa vào hàng đợi tác vụ vi mô. Cuối cùng, "End" sẽ được in ra. Vòng lặp sự kiện kiểm tra hàng đợi tác vụ vi mô và thực thi hàm callback của Promise, và cuối cùng là hàm callback của setTimeout.
Kết Luận
Tóm lại, Web API xử lý các tác vụ bất đồng bộ bên ngoài luồng chính của JavaScript. Vòng lặp sự kiện sẽ di chuyển các tác vụ từ hàng đợi tác vụ hoặc hàng đợi tác vụ vi mô vào ngăn xếp cuộc gọi. Các tác vụ vi mô cần được xử lý trước các tác vụ trong hàng đợi tác vụ. Hiểu rõ cơ chế hoạt động của vòng lặp sự kiện sẽ giúp bạn làm chủ JavaScript và xây dựng các ứng dụng web hiệu quả và mượt mà hơn.
source: viblo