Giải thích về Node.js Event Loop

Node.js sử dụng một luồng (single thread) duy nhất. Bạn có thể thắc mắc làm thế nào nó có thể xử lý hàng ngàn yêu cầu cùng một lúc.

Bí mật chính là Event Loop.

Thay vì chờ đợi một tác vụ hoàn thành, Node.js gửi các tác vụ tốn thời gian cho hệ điều hành. Nó tiếp tục chuyển sang tác vụ tiếp theo. Điều này giúp ứng dụng của bạn chạy nhanh và phản hồi tốt.

Blocking vs Non-blocking

Nếu bạn sử dụng các hàm đồng bộ như readFileSync, máy chủ sẽ dừng lại. Nó phải đợi cho đến khi việc đọc tệp hoàn tất. Không người dùng nào khác nhận được phản hồi. Điều này sẽ làm giảm hiệu suất của bạn.

Nếu bạn sử dụng fs.readFile, máy chủ vẫn tiếp tục chạy. Nó xử lý các yêu cầu khác trong khi tệp đang được đọc ở chế độ nền.

Cách thức hoạt động của Event Loop

Vòng lặp di chuyển qua nhiều giai đoạn:

• Timers: Xử lý setTimeoutsetInterval. • Pending Callbacks: Xử lý các lỗi ở cấp độ hệ thống. • Poll: Tiếp nhận các kết nối mới và xử lý I/O như các truy vấn cơ sở dữ liệu. • Check: Xử lý setImmediate. • Close Callbacks: Xử lý việc đóng socket.

Thứ tự ưu tiên

Không phải mọi tác vụ đều như nhau. Node.js sử dụng hai hàng đợi:

  1. Microtask Queue: Hàng đợi này chứa các Promise.
  2. Callback Queue: Hàng đợi này chứa setTimeout và I/O.

Microtask Queue luôn được chạy trước. Nếu bạn có một Promise và một setTimeout, Promise sẽ hoàn thành trước bộ hẹn giờ.

Call Stack và các hàng đợi

Call Stack theo dõi mã nguồn nào đang được thực thi ngay lúc này. Khi một tác vụ hoàn thành, callback của nó sẽ đi vào một hàng đợi. Event Loop sẽ đợi cho đến khi Call Stack trống trước khi lấy các tác vụ từ hàng đợi ra.

Tránh những sai lầm sau:

• Không sử dụng vòng lặp vô tận. Điều này sẽ làm đóng băng toàn bộ ứng dụng của bạn. • Không sử dụng các phương thức tệp đồng bộ trong môi trường production. • Không chạy các tác vụ tính toán nặng hoặc xử lý video trên luồng chính (main thread).

Đối với các tác vụ nặng, hãy sử dụng Worker Threads hoặc các tác vụ chạy ngầm (background jobs).

Tóm tắt

Node.js nhanh vì nó không chờ đợi. Nó ủy thác các tác vụ I/O và sử dụng Event Loop để quản lý kết quả. Kiến trúc này cho phép một luồng duy nhất có thể phục vụ nhiều người dùng.

Phần nào của Event Loop khiến bạn thấy khó học nhất? Hãy cho tôi biết ở phần bình luận nhé.

Nguồn: https://dev.to/synfinity-dynamics-pvt-ltd/nodejs-event-loop-explained-how-nodejs-handles-thousands-of-concurrent-requests-1heo