How I understood setImmediate()
Tags: node, javascript
Published: 2021-03-29 09:53:35

####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:
```javascript

console.log("before immediate");

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

console.log("after immediate");
```

Output would be:
```javascript
before immediate
after immediate
executing immediate: immediately
```

Now let us move the setImmediate block inside a function and check execution:
```javascript
function test() {
  setImmediate((arg) => {
    console.log(`executing immediate: ${arg}`);
  }, "immediately");
}
test();

console.log("before immediate");
console.log("after immediate");
```
Output:
```javascript
before immediate
after immediate
executing immediate: immediately
```

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 .
```javascript
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");
```

Output on 1st execution:
```javascript
before immediate
after immediate
executing timeout: hi
executing immediate: immediately
```
Output on 2nd execution:
```javascript
before immediate
after immediate
executing immediate: immediately
executing timeout: hi
```
Output on 3rd execution:
```javascript
before immediate
after immediate
executing timeout: hi
executing immediate: immediately
```

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

```javascript
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");
```
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.
```javascript
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");

```

Output would be:
```javascript
before immediate
after immediate
executing immediate: 1
executing immediate: 2
executing immediate: 3
executing timeout: 1
executing timeout: 2
executing timeout: 3
```
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..