Why is the behavior of setTimeout(0) and setImmediate() undefined when used in the main module?

1k Views Asked by At

Take the following code taken from the nodejs event loop documentation :

// timeout_vs_immediate.js
setTimeout(() => {
  console.log('timeout');
}, 0);

setImmediate(() => {
  console.log('immediate');
});

According to the documentation :

For example, if we run the following script which is not within an I/O cycle (i.e. the main module), the order in which the two timers are executed is non-deterministic, as it is bound by the performance of the process.

Why is the above statement true ? Is it because the nodejs runtime actually employs more than one thread to pick out the callbacks that have to be executed.

What my intuition says: there are two threads that execute callbacks for setTimeout and setImmediate so when both of them are available this leads to a race condition, and thus the output will be non-deterministic.

Is it correct ? Or is there any other reason for which this is non-deterministic ?

1

There are 1 best solutions below

1
On

Essentially, two things happen:

  1. setTimer(0..) gets converted into setTimer(1..)
  2. before the (next) event loop tick begins, node/libuv has to perform a clock_gettime() to get the current time from the system. The time taken for this system call is non deterministic as it depends on the system load at that time. Now, if clock_gettime() took more than 1ms, the setTimer callback will run (#), else event loop continues to next phase (##).

    • In case (#), setTimeout(0,..) callback is run before setImmediate()
    • In case (##), it is otherwise.

Reference: https://github.com/nodejs/help/issues/392#issuecomment-305969168