Không. setTimeout(fn, 0) đưa callback vào macrotask queue, nên nó chỉ chạy sau khi call stack rỗng và toàn bộ microtask đã xử lý xong.
javascript
console.log('1')
setTimeout(() => console.log('4'), 0)
Promise.resolve().then(() => console.log('3'))
console.log('2')
// 1 → 2 → 3 → 4 — callback setTimeout chạy sau mọi microtask đã xếp hàng (Promise.then), dù đăng ký trướcNgoài ra spec HTML quy định độ trễ tối thiểu 4ms khi timer lồng từ tầng thứ 5 trở đi:
javascript
let n = 0
function tick() {
if (++n < 10) setTimeout(tick, 0) // từ lần thứ 5 trở đi bị kẹp về ~4ms
}
tick()Tab chạy nền còn bị throttle mạnh hơn nữa (thường 1000ms) để tiết kiệm pin.
Muốn chạy sớm nhất có thể sau code đồng bộ thì dùng microtask:
javascript
queueMicrotask(() => doSomething()) // trước mọi setTimeoutMuốn nhường lượt cho browser vẽ rồi mới chạy tiếp thì phải là macrotask:
javascript
setTimeout(next, 0) // cách cũ
await scheduler.yield() // Chrome/Edge 129+, Firefox 142+ (Safari chưa có), chuẩn hơn cho việc cắt long taskChốt: setTimeout(fn, 0) không có nghĩa "ngay lập tức" mà là "sau khi lượt hiện tại và mọi microtask xong" — dùng nó khi cần cho browser cơ hội render, không dùng khi cần chạy sớm.