TopDev AI Robot TopDev
#Backend & Microservices#Giải đề & Thuật toán

Bản chất Event Loop trong Node.js: Phân biệt process.nextTick(), setImmediate() và Promise

Thu Trang (Backend Engineer)
📖 2 phút đọc 💬 1 phản hồi
⚡ Tóm tắt 30 giây bởi TopDev AI
AI Overview

Câu hỏi kiểm tra bản chất lập trình bất đồng bộ Hãy dự đoán thứ tự in ra màn hình của đoạn mã sau: Nếu bạn không thể giải thích chính xác tại sao nextTick lại chạy trước Promise, hoặc khi nào setImme…

☰ Mục lục bài viết (5 phần) Mở / Đóng mục lục

Câu hỏi kiểm tra bản chất lập trình bất đồng bộ#

Hãy dự đoán thứ tự in ra màn hình của đoạn mã sau:

JAVASCRIPT
console.log('1 - Start');

setTimeout(() => console.log('2 - setTimeout'), 0);

setImmediate(() => console.log('3 - setImmediate'));

Promise.resolve().then(() => console.log('4 - Promise'));

process.nextTick(() => console.log('5 - nextTick'));

console.log('6 - End');

Nếu bạn không thể giải thích chính xác tại sao nextTick lại chạy trước Promise, hoặc khi nào setImmediate chạy trước setTimeout, bạn chưa thực sự làm chủ Event Loop của Node.js (dựa trên thư viện libuv).

Sơ đồ các pha (Phases) của Node.js Event Loop#

CODE
   ┌───────────────────────────┐
┌─>│           Timers          │ (setTimeout, setInterval)
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     Pending Callbacks     │ (I/O callbacks hệ thống)
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │        Idle, Prepare      │ (Dùng nội bộ)
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │           Poll            │ (Lấy sự kiện I/O mới)
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │           Check           │ (setImmediate callbacks)
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      Close Callbacks      │ (socket.on('close'))
   └───────────────────────────┘

Cơ chế Microtask Queue và process.nextTick()#

Bên cạnh các pha chính trên (Macrotasks), Node.js có 2 hàng đợi ưu tiên đặc biệt (Microtask Queues):

  1. nextTick Queue: Chứa các callback đăng ký qua process.nextTick().
  2. Other Microtask Queue: Chứa các Promise resolve/reject callbacks.

Quy tắc: Bất cứ khi nào JavaScript call stack rỗng (sau khi chạy xong synchronous code hoặc giữa các pha của Event Loop), Node.js sẽ lập tức vét sạch toàn bộ hàng đợi nextTick, sau đó vét tiếp hàng đợi Promise trước khi chuyển sang pha tiếp theo!

Đáp án chính xác và Thứ tự thực thi#

CODE
1 - Start
6 - End
5 - nextTick       (Ưu tiên số 1 trong microtasks)
4 - Promise        (Ưu tiên số 2 trong microtasks)
2 - setTimeout     (Pha Timers)
3 - setImmediate   (Pha Check)

Góc thảo luận#

Tại sao việc lạm dụng process.nextTick() lồng nhau có thể làm "bỏ đói" (I/O starvation) toàn bộ hệ thống của bạn?


Xem thêm nội dung liên quan:

Chia sẻ thảo luận này:

Thảo luận

1 phản hồi

Ý kiến từ cộng đồng kỹ sư TopDev
💬

Tham gia thảo luận

Cộng đồng mở · Đăng nhập 1-chạm qua Google
  1. Hoàng Nam (Tech Lead)
    #1

    Bổ sung thêm: Nếu đặt setTimeout(..., 0) và setImmediate(...) bên trong một callback I/O (ví dụ fs.readFile), thì setImmediate LUÔN LUÔN chạy trước setTimeout vì lúc đó Event Loop đang nằm ở pha Poll, pha tiếp theo ngay sau Poll là Check!

Bài liên quan trong #Backend & Microservices

1
TopDev AI Companion
AI
✓ Đã sao chép link