Predicting Execution Order
Event-loop questions often ask:
What logs first?You can predict most beginner examples with a simple process.
The Basic Rule
Use this order:
- Run synchronous code.
- Run microtasks.
- Run macrotasks.
Short version:
Stack -> Microtasks -> TasksExample 1
console.log("A");
setTimeout(() => {
console.log("B");
}, 0);
Promise.resolve().then(() => {
console.log("C");
});
console.log("D");Output:
A
D
C
BWhy?
Synchronous:
A
DMicrotask:
CMacrotask:
BExample 2: Multiple Promises
console.log("Start");
Promise.resolve().then(() => {
console.log("Promise 1");
});
Promise.resolve().then(() => {
console.log("Promise 2");
});
console.log("End");Output:
Start
End
Promise 1
Promise 2Microtasks run in the order they were queued.
Example 3: Microtask Creates Another Microtask
Promise.resolve().then(() => {
console.log("A");
Promise.resolve().then(() => {
console.log("B");
});
});
setTimeout(() => {
console.log("C");
}, 0);Output:
A
B
CThe microtask queue drains before the timer task runs.
Example 4: Timer Creates a Promise
setTimeout(() => {
console.log("Timer 1");
Promise.resolve().then(() => {
console.log("Promise inside timer");
});
}, 0);
setTimeout(() => {
console.log("Timer 2");
}, 0);Output:
Timer 1
Promise inside timer
Timer 2After one task runs, microtasks are processed before the next task.
Example 5: Already Resolved Promise
const promise = Promise.resolve("Done");
console.log("A");
promise.then((value) => {
console.log(value);
});
console.log("B");Output:
A
B
DoneAlready resolved does not mean .then() runs immediately.
It still queues a microtask.
Prediction Checklist
When solving event-loop order:
- Mark all synchronous logs.
- Put promise callbacks in the microtask queue.
- Put timers/events in the task queue.
- Run all synchronous code first.
- Drain microtasks.
- Run one task.
- Drain microtasks again.
- Repeat.
Common Sources
Synchronous:
console.log("sync");Microtask:
Promise.resolve().then(callback);
queueMicrotask(callback);Macrotask:
setTimeout(callback, 0);
setInterval(callback, 1000);Best Practices
Do not write production code that depends on tricky timing unless necessary.
Prefer clear async flow with promises and async / await.
Use event-loop knowledge to debug, not to make code clever.
When in doubt, break examples into stack, microtasks, and tasks.
Common Mistakes
Mistake 1: Running Timers Before Promises
Promise callbacks are microtasks.
They run before timer tasks.
Mistake 2: Thinking Resolved Promises Are Synchronous
.then() still runs later as a microtask.
Mistake 3: Forgetting Microtasks After Each Task
After a timer callback runs, any microtasks it creates run before the next timer callback.
Summary
You can predict many event-loop examples with one model:
Stack -> Microtasks -> Tasks- Synchronous code runs first.
- Promise callbacks are microtasks.
- Timer callbacks are tasks.
- Microtasks drain before the next task.
- Each task is followed by another microtask checkpoint.
- Use event-loop knowledge to debug async behavior clearly.