js
console.log('1')
setTimeout(() => console.log('2'), 0)
Promise.resolve().then(() => console.log('3'))
console.log('4')Kết quả: 1, 4, 3, 2.
1và4là code đồng bộ, chạy hết trước mọi thứ khác.3nằm trong microtask queue (callback của Promise). Microtask được rút cạn ngay sau khi call stack rỗng, trước khi event loop nhận task mới.2là callback củasetTimeout— một macrotask (task). Dù đặt delay0, nó phải đợi lượt task kế tiếp của event loop, tức là sau toàn bộ microtask.
Quy tắc để trả lời mọi câu dạng này:
1. Chạy hết code đồng bộ.
2. Rút cạn microtask queue (.then, await phần sau, queueMicrotask, MutationObserver).
3. Lấy một macrotask (setTimeout, setInterval, event handler, I/O) rồi lặp lại từ bước 2.
Hệ quả cần nhớ: một microtask sinh ra microtask khác thì vẫn được xử lý trong cùng vòng — nếu tạo microtask vô hạn, trình duyệt sẽ không bao giờ render lại.