Microtask vs Macrotask in JavaScript — With Node.js vs Browser Notes

2026-11-04来源 dev.toEnglish
Microtask vs Macrotask in JavaScript — With Node.js vs Browser Notes

Recap (Browser)

  • Microtasks: Promise.then/catch/finally, queueMicrotask, MutationObserver
  • Macrotasks: setTimeout, setInterval, requestAnimationFrame, DOM events
  • Order per tick: run script → drain all microtasks → possibly render → then the next macrotask.

Node.js Event Loop Differences

Node.js has phases in its event loop (simplified):

1) Timers → setTimeout / setInterval callbacks

2) Pending Callbacks

3) Poll → I/O callbacks; may block waiting for I/O

4) Check → setImmediate callbacks

5) Close Callbacks

After each phase, Node runs microtask queues in this order:

  • process.nextTick queue (✅ runs before promise microtasks)
  • Promise microtasks (jobs scheduled by Promise.then / queueMicrotask)

Key takeaways

  • process.nextTick always runs before other microtasks and before moving to the next phase. Overuse can starve the loop.
  • setImmediate runs in the Check phase.
  • setTimeout(..., 0) runs in the Timers phase of a later tick.
  • Order of setTimeout(…,0) vs setImmediate can vary:
    • After I/O, setImmediate tends to run first (since the loop is already at the Check phase).
    • Without I/O, timers may run first (implementation- and timing-dependent).

Example: Node.js ordering

// node-order.js setTimeout(() => console.log('timeout'), 0); setImmediate(() => console.log('immediate')); Promise.resolve().then(() => console.log('promise microtask')); process.nextTick(() => console.log('nextTick microtask')); 

Typical Node output:

nextTick microtask promise microtask [ either 'immediate' or 'timeout' first, scenario-dependent ] 

Why:

  • process.nextTick runs before other microtasks.
  • Promise microtasks run next.
  • Then the loop continues to a phase where either setImmediate or setTimeout fires first.

Tip: If you place the scheduling inside an I/O callback (e.g., fs.readFile), setImmediate is more likely to run before setTimeout.

Example: Browser ordering

<script> setTimeout(() => console.log('timeout'), 0); Promise.resolve().then(() => console.log('promise microtask')); // process.nextTick / setImmediate are Node-only </script> 

Browser output:

promise microtask timeout 

Quick Matrix

API / Concept Browser Microtask Browser Macrotask Node Microtask Node Macrotask
Promise.then ✔️ ❌ ✔️ ❌
queueMicrotask ✔️ ❌ ✔️ ❌
MutationObserver ✔️ ❌ ❌ (browser only) ❌
setTimeout / setInterval ❌ ✔️ ❌ ✔️ (Timers)
requestAnimationFrame ❌ ✔️ (render step) ❌ ❌
setImmediate ❌ ❌ ❌ ✔️ (Check)
process.nextTick ❌ ❌ ✔️ (before other microtasks) ❌

Mental Model 🧠

  • Browser: script → microtasks (Promises) → macrotask (timeout) → render.
  • Node: phase → nextTick → Promise microtasks → next phase; setImmediate in Check, timers in Timers.

Use process.nextTick sparingly (it’s too eager), and prefer Promise microtasks for normal “run right after” semantics.

Microtask vs Macrotask — Visual Diagram

This diagram shows how a microtask (Promise) runs before a macrotask (setTimeout) after the script finishes.

Microtask vs Macrotask — Visual Diagram

That’s it — now you can reason about microtasks/macrotasks across both environments with confidence.

Originally published on Bitlyst.

原文:https://www.a8q9.cn/en/article/microtask-vs-macrotask-in-javascript-with-node-js-vs-browser-notes-248002.html

相关文章