Interesting question. In order to understand the reason, one needs to understand the JavaScript event loop.
.then()
queues a microtask. Microtasks are executed as soon as the JS call stack empties.
In this case (but not in all cases), setTimeout
queues a task in the main task queue. Tasks are queued for external events, timer handlers, rendering (in the browser), etc... If a task calls JS code, the next task will not run until all the microtasks associated with it finish running.
So here's what's happening:
- Task #1, queued internally by Node.js:
console.log(1)
logs 1
. Output is 1
setTimeout(() => { console.log(3) });
queues a task to log 3
Promise.resolve().then(() => console.log(4))
queues a microtask to log 4
console.log(7)
logs 7
. Output is 1 7
.
- The JS stack empties, because there's no more statements. The microtasks begin to execute.
- Microtask #1-1, queued by
.then()
:
- Logs
4
. Output is 1 7 4
.
- Task #2, queued by
setTimeout()
:
- Logs
3
. Output is 1 7 4 3
.
- The JS stack empties, because there's no more statements, however there are no microtasks.
Final output:
1
7
4
3