Node.js › Async Patterns
What is the difference between micro tasks and macro tasks in Node.js's event loop, and how does this affect Promise callback ordering?
IntermediateAnswer
Microtasks (Promise .then()/.catch()/.finally() callbacks, and process.nextTick() callbacks which have their own even-higher-priority queue) are processed completely -- draining the entire microtask queue -- after each single macrotask, before the event loop moves on to the next phase. Macrotasks include timers (setTimeout/setInterval), I/O callbacks, and setImmediate() callbacks, each processed one at a time per event loop phase. This is why a resolved promise's .then() callback always runs before a setTimeout(fn, 0) callback, even though both appear to be scheduled for 'immediately'.
console.log('1');
setTimeout(() => console.log('2 (macrotask)'), 0);
Promise.resolve().then(() => console.log('3 (microtask)'));
console.log('4');
// Output order: 1, 4, 3, 2 -- microtasks always drain before the next macrotaskReal-world example A developer debugging unexpected ordering in a logging system realizes that a Promise-based logger's output was appearing before a setTimeout-scheduled cleanup task's output specifically because of this microtask/macrotask distinction, not because of any bug in either piece of code.