Note: This answer is for the execution model according to the HTML specification. However, the question is about nodejs.
With setTimeout(), timers are created to enqueue tasks. You call it twice, which create:
- A timer with timeout of 100 to enqueue a task that logs "C".
- A timer with timeout of 0 to enqueue a task that logs "D".
So the timer "for C" is created before the timer "for D". But timers run in parallel, and are not in a queue; instead, they enqueue their tasks into the so-called task queue. (You may have confused timers running parallely, tasks and the task queue!)
In your case:
- The timer "for D" enqueues its task first. The task queue now holds the task "for D".
- The timer "for C" enqueues its task second. The task queue now holds the tasks "for D" and "for C", in this order.
They may not have executed until now, e.g. because of someSynchronousTask() taking too long. So only once the event loop was free would the tasks of the task queue run, in this order:
- The task that logs D first.
- The task that logs C second.
This is your observed behaviour.
In conclusion: setTimeout() doesn't enqueue tasks directly, but creates timers which enqueue tasks after some time. The final order of the task queue depends on when the timers run, not when they are created.
An analogy to "issued one way, done in reverse":
Imagine you tell a friend to meet up together in 10 minutes.
Then you tell them to ask now (0 minutes) whether others would join the meet-up, too.
So your friend asks around first, then meets up in 10 minutes; even though you had told these in reverse. But according to your given times, the events were planned in this order.
setTimeout(() => console.log('E'), 1);one with a delay of1. I'll bet anything that it'sD -> E -> C. Docs are here