Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Node.js event loop. process.nextTick() never invoked. Why?

Tags:

node.js

events

I am experimenting with the event loop. First I begin with this straightforward code to read and print the contents of a file:

var fs = require('fs');
var PATH = "./.gitignore";

fs.readFile(PATH,"utf-8",function(err,text){
    console.log("----read: "+text);
});

Then I place it into an infinite loop. In this case, the readFile function is never executed. If I am not mistaken it's because Node's single thread is busy iterating without letting I/O calls be executed.

while(true){
    var fs = require('fs');
    var PATH = "./.gitignore";

    fs.readFile(PATH,"utf-8",function(err,text){
        console.log("----read: "+text);
    });
}

So, I would like to do something so that I/O calls are assigned process time intertwined with the loop. I tried with process.nextTick() but it doesn't work:

while(true){
    process.nextTick(function(){
        fs.readFile(PATH,"utf-8",function(err,text){
            console.log("----read: "+text)
        });
    });
}

Why isn't it working and how could I make it?

like image 824
codependent Avatar asked Oct 09 '14 09:10

codependent


People also ask

How process nextTick () works in node JS?

nextTick ( ) is not the part of any phase of event loop. Instead, nextTickQueue will process all the callbacks after completing current iteration and before starting the next iteration of event loop. process. nextTick ( ) schedule a callback function to be executed in next iteration of event loop.

What is the difference between process nextTick () and setImmediate ()?

process. nextTick() is used to schedule a callback function to be invoked in the next iteration of the Event Loop. setImmediate() method is used to execute a function right after the current event loop finishes.

How does event loop work in node JS?

Event loop is an endless loop, which waits for tasks, executes them and then sleeps until it receives more tasks. The event loop executes tasks from the event queue only when the call stack is empty i.e. there is no ongoing task. The event loop allows us to use callbacks and promises.

What will happen if the call stack and the event loop are empty in Node?

If there is no other message in the queue, and the stack is empty, the message is processed right after the delay. However, if there are messages, the setTimeout message will have to wait for other messages to be processed.


1 Answers

Because your while loop is still running. It's just infinitely adding things to do in the next tick. If you let it go, your node process will crash as it runs out of memory.

When you work with async code, your normal loops and control structures tend to trip you up. The reason is that they execute synchronously in one step of the event loop. Until something happens that yields control to the event loop again, nothing 'nextTick' will happen.

Think of it like this, You are in Pass B of the event loop when your code runs. When you call

process.nextTick(function foo() { do.stuff(); })' 

you are adding the foo to the list of 'things to do before you start pass C of the event loop.' Every time you call nextTick, you add one more thing to the list, but none of them will run until the synchronous code is done.

What you need to do instead is create 'do the next thing' links in your callbacks. Think linked-lists.

// var files = your list of files;
function do_read(count) {
     var next = count+1;
     fs.readFile(files[count], "utf-8", function(err,text) {
         console.log("----read: " + text);

         if (next < files.length) {
            // this doesn't run until the previous readFile completes.
            process.nextTick(function() { do_read(next) });
         }
     });
}
// kick off the first one:
do_read(files[0], 0);

(obviously this is a contrived example, but you get the idea)

This causes each 'next file' to be added to the 'nextTick' to-do queue only after the previous one has been fully processed.

TL;DR: Most of the time, you don't want to start it doing the next thing until the previous thing is completed

Hope that helps!

like image 200
JayKuri Avatar answered Oct 05 '22 01:10

JayKuri