Nhiều Junior vẫn không trả lời được câu này. Điểm khác nhau giữa setTimeout, setImmediate, và process.nextTick 😊 (Series: Bí kíp Javascript - PHẦN 17)
Điểm khác nhau giữa setTimeout(callback, 0)
, setImmediate(callback)
và process.nextTick(callback)
là gì?
Một câu hỏi rất hay được sử dụng để phỏng vấn các Javascript Junior (Trước mình cũng bị hỏi một lần :D
). Giờ mới hiểu, câu này ngoài việc phân biệt điểm khác nhau giữa các function
trên thì vừa check rằng bạn có thực sự hiểu về Event Loop
hay không.
Bề ngoài, có vẻ như cả ba hàm đều làm điều tương tự - chúng thực hiện lệnh callback sau event loop hiện tại, nhưng trước bất kỳ thứ gì khác. Câu hỏi tự nhiên cần đặt ra là, tại sao lại có ba function
khác nhau? Hãy thử chạy đoạn code sau:
let racer = function() {
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
console.log("current event loop");
}
racer()
Chúng ta có thể thấy từ output
các lệnh callback
này không được thực thi theo đúng thứ tự mà chúng đã được viết trong source code.
current event loop
nextTick
timeout
immediate
Giải thích
Hàm được xử lý đầu tiên là process.nextTick
, đặt lệnh callback
của nó ở đầu hàng đợi sự kiện. Nó sẽ thực thi sau khi code hiện đang được thực thi nhưng trước bất kỳ sự kiện I/O
hoặc bộ hẹn giờ (Timer
) nào.
Tiếp theo là “timeout”
. Vì chúng ta đã passed thời gian chờ là 0
cho setTimeout
, nên không có thêm độ trễ bắt buộc nào trước khi thực thi và nó được đưa vào hàng đợi Timer
trong Event loop
tiếp theo.
Cuối cùng, chúng ta có setImmediate
, mà rõ ràng không phải là ngay lập tức như tên của nó! Callback
của nó được đặt trong hàng đợi và kiểm tra chu kỳ tiếp theo của event loop
. Vì hàng đợi check
xảy ra muộn hơn hàng đợi Timer
, setImmediate
sẽ chậm hơn setTimeout 0
. (Từ từ đừng bối rối nhìn hình sau sẽ rõ
)
Nói chung, event loop
sẽ trông như thế này:
timers
-> I/O
-> poll
-> check
-> close
-> timers
-> ... (Cứ lặp mãi như vậy nên gọi là event loop
)
timers : gọi callback
từ setInterval
hoặc setTimeout
I/O : gọi callback
từ các sự kiện I/O (mình cũng có giải thích về cái này ở đây)
Idle : Được sử dụng nội bộ bởi Node giữa các pha IO
và Poll
poll : Truy xuất các sự kiện I/O mới
check : gọi callbacks
từ setImmediate
close : Xử lý đóng các kết nối như là Socket
Xem ví dụ sau và bạn sẽ hiểu được cách nó hoạt động
Bạn nghĩ output
của đoạn code
sau là gì?
let racer1 = function () {
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
};
let racer2 = function () {
process.nextTick(() => console.log("nextTick"));
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
};
let racer3 = function () {
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
setTimeout(() => console.log("timeout"), 0);
};
racer1();
racer2();
racer3();
Đây có phải là những gì bạn nghĩ?
nextTick
nextTick
nextTick
timeout
timeout
timeout
immediate
immediate
immediate
Mình hy vọng bạn thích bài viết này và học thêm được điều gì đó mới.
Donate mình một ly cafe hoặc 1 cây bút bi để mình có thêm động lực cho ra nhiều bài viết hay và chất lượng hơn trong tương lai nhé. À mà nếu bạn có bất kỳ câu hỏi nào thì đừng ngại comment hoặc liên hệ mình qua: Zalo - 0374226770 hoặc Facebook. Mình xin cảm ơn.
Momo: NGUYỄN ANH TUẤN - 0374226770
TPBank: NGUYỄN ANH TUẤN - 0374226770 (hoặc 01681423001)
All rights reserved