3

hoping for a little confirmation on understanding of node.js execution model. I understand that when node.js process starts, this is the sequence of executions: enter image description here (from Jonas Schmedtmann's Udemy node.js course)

With the main takeaway being that top-level code is always executed first before any callbacks.

Then, in the event-loop, this is the sequence of the 'phases': enter image description here

After some digging, I also confirmed why a setTimeout and a setImmediate called in the main module has 'arbitrary' execution order, but when called from the I/O phase, the setImmediate will always execute first, based on this post: https://github.com/nodejs/help/issues/392#issuecomment-274032320.

(Reason: assuming the timer threshold has already passed, since we are currently in the I/O phase, and the next phase after that is the check-handles phase where setImmediate callbacks are executed, immediate always executes before timer.)

Now, when timer and immediate callbacks are called from a phase such that the next phase is the due-timers phase (such as from main module), if the top-level code took long enough that the timer is due, the timer callback will always execute first, correct? I've tested this with the following code, and it seems to be true (everytime I've run it, timer executes first, even though it has a full second delay compared to the immediate callback)

setTimeout(() => {
  console.log('timer completed');
}, 1000);

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

for (let i = 0; i < 5000; i++) {
  console.log(`top-level code: ${i}`);
}

So here is my question: shouldn't an I/O operation callback also be executed before the immediate's callback due to the event-loop, assuming that the top-level code takes long enough that the I/O operation completes by the time we start the event-loop?

However, this code below suggests otherwise, as the execution order is always: top-levels->timer->immediate->io

Even though based on the model above I should be expecting: top-levels->timer->io->immediate (?)

setTimeout(() => {
  console.log('timer completed');
}, 1000);

fs.readFile('test-file.txt', 'utf-8', () => {
  console.log('io completed');
});

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

for (let i = 0; i < 5000; i++) {
  console.log(`top-level code: ${i}`);
}

Thank you!

2
  • to clarify, this behavior seems to suggest that io operations "start" after the event-loop starts, because no matter how long the top-level code takes to run, it's still not ready by the time the event-loop starts, whereas timers "start" before the event-loop starts, as it is already due if the top-level code takes long enough to execut. Is this true/the correct reason? Commented Feb 13, 2020 at 0:09
  • I'm not sure if it's related, but also remember that the actual I/O operations occur in a separate thread in the event loop's "thread pool". Maybe you see the IO last as it takes longer - so it is actually polled in the "next iteration" of the event loop... Commented Oct 3, 2021 at 15:07

1 Answer 1

0

I might be a little late to answering this question and it is possible you've already figured this one out @M.Lee. But here goes the answer to your question:

During the top-level code execution the code you're running in your example is not running in the event loop. Like the first image from your question shows, event loop will start ticking after the top level code is already executed. So, when it comes to the top-level code, Node does not follow the same order that it follows during an event loop tick.

In this particular case, the I/O callback is getting executed the last is plainly because the contents of this particular file (BTW, I had to go ahead and do the research by looking at Jonas' Node course and understand what this file contained. It just contains the line "Node.js is the best!" 1 million times).

Also a side note here is that you're using the asynchronous readFile function instead of the readFileSync.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.