Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 ?

like image 364
ng.newbie Avatar asked Aug 29 '17 08:08

ng.newbie


1 Answers

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

like image 69
human Avatar answered Oct 16 '22 23:10

human