DEV Community

Mitesh Kamat
Mitesh Kamat

Posted on

How I understood setImmediate()

This post is about understanding the execution order of setImmediate() in node js environment.

As per official nodejs documentation related to setImmediate which is as follows:

setImmediate() will execute code at the end of the current event loop cycle. This code will execute after any I/O operations in the current event loop and before any timers scheduled for the next event loop. This code execution could be thought of as happening "right after this", meaning any code following the setImmediate() function call will execute before the setImmediate() function argument.

For example:


console.log("before immediate");

setImmediate((arg) => {
  console.log(`executing immediate: ${arg}`);
}, "immediately");

console.log("after immediate");
Enter fullscreen mode Exit fullscreen mode

Output would be:

before immediate
after immediate
executing immediate: immediately
Enter fullscreen mode Exit fullscreen mode

Now let us move the setImmediate block inside a function and check execution:

function test() {
  setImmediate((arg) => {
    console.log(`executing immediate: ${arg}`);
  }, "immediately");
}
test();

console.log("before immediate");
console.log("after immediate");
Enter fullscreen mode Exit fullscreen mode

Output:

before immediate
after immediate
executing immediate: immediately
Enter fullscreen mode Exit fullscreen mode

Let's compare it with setTimeout() w.r.t the scope they are declared in.
When we have the timers declared in the main module i.e. not within any I/O cycle .

console.log("before immediate");

setImmediate((arg) => {
  console.log(`executing immediate: ${arg}`);
}, "immediately");

setTimeout(
  (arg) => {
    console.log(`executing timeout: ${arg}`);
  },
  0,
  "hi"
);

console.log("after immediate");
Enter fullscreen mode Exit fullscreen mode

Output on 1st execution:

before immediate
after immediate
executing timeout: hi
executing immediate: immediately
Enter fullscreen mode Exit fullscreen mode

Output on 2nd execution:

before immediate
after immediate
executing immediate: immediately
executing timeout: hi
Enter fullscreen mode Exit fullscreen mode

Output on 3rd execution:

before immediate
after immediate
executing timeout: hi
executing immediate: immediately
Enter fullscreen mode Exit fullscreen mode

Now even if you put them inside a function the output will be same i.e. non-deterministic

console.log("before immediate");
function first() {
  setImmediate((arg) => {
    console.log(`executing immediate: ${arg}`);
  }, "immediately");
  setTimeout(
    (arg) => {
      console.log(`executing timeout:${arg}`);
    },
    0,
    "hi"
  );
}
first();
console.log("after immediate");
Enter fullscreen mode Exit fullscreen mode

Execute multiple times and compare the output.

If we create an I/O cycle like reading a file or accessing any resource from disk, then how will the timers behave.

var fs = require("fs"); //module to read a file on disk
console.log("before immediate");

fs.readFile("readFile.txt", () => {
  setTimeout(
    (arg) => { console.log(`executing timeout: ${arg}`);},0,"1"
  );
  setTimeout(
   (arg) => {console.log(`executing timeout:${arg}`) ;},0,"2"
  );
  setTimeout(
    (arg) => {console.log(`executing timeout:${arg}`);},0,"3"
  );
  setImmediate((arg) => {
    console.log(`executing immediate: ${arg}`);
  }, "1");
  setImmediate((arg) => {
    console.log(`executing immediate: ${arg}`);
  }, "2");
  setImmediate((arg) => {
    console.log(`executing immediate: ${arg}`);
  }, "3");
});

console.log("after immediate");

Enter fullscreen mode Exit fullscreen mode

Output would be:

before immediate
after immediate
executing immediate: 1
executing immediate: 2
executing immediate: 3
executing timeout: 1
executing timeout: 2
executing timeout: 3
Enter fullscreen mode Exit fullscreen mode

Even if you repeat this execution multiple times , it would return the same output.

So the basic takeaway from this is: if both these timers are executed inside an I/O operation or task setImmediate() will always execute ahead of setTimeout().

That's what I learnt repeating this execution multiple times and in different context's.

Cheers..

Top comments (0)