ng.newbie
ng.newbie

Reputation: 3218

Why does a listener on the process.stdin keep node from terminating?

I am a Java programmer trying to understand node. What does not make sense to me is how the following code keeps the process from terminating ?

process.stdin.on('data', function(data) {
 console.log('Foobar');
        }
);

This just raises so many questions -:

  1. Will NodeJs continue to run if there are listeners attached to anything or just the global process object ?
  2. Why will NodeJs not terminate if there are listeners attached ?
  3. Is this a behavior only for the data event ? Or do other events also result in the same behavior ?
  4. What are the other ways a node process can be kept from terminating ?

Upvotes: 3

Views: 2397

Answers (3)

shaochuancs
shaochuancs

Reputation: 16226

Update:

According to the Event Loop document, technically speaking:

Node.js checks if it is waiting for any asynchronous I/O or timers and shuts down cleanly if there are not any.


According to the Node.js Process document:

Normally, the Node.js process will exit when there is no work scheduled

So, whether or not Node.js will be terminated depends on whether there are scheduled-work left.

For your process.stdin.on('data'... example, when the code is finished execution, there is still work scheduled -- user input should be captured and handled. Thus, the Node.js process won't be terminated.

Another example would be HTTP request. If Node.js send an HTTP request, which will take 30 seconds to return, the Node.js process won't be terminated until the response is retrieved and handled -- unless all scheduled work is done, Node.js process will keep running.

Of course, whether the scheduled work is "done" is defined by Node.js -- in HTTP request case, if you just send the request and don't care about the response (no response handler), there would be 2 ways to define this scheduled work as "done": A. HTTP request is sent and that's all. B. HTTP request is sent and response is retrived, no matter there are any response handler. Node.js choose strategy B.

The third example is custom event and its event listener. Consider the following code:

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

When this code execution is completed, although there is still event listener existed, the Node.js process will be terminated, as Node.js detected that no scheduled work exists any more -- no code is running and no other handler is waiting, thus custom events would never be triggered again.

Thus, for your 4 questions:

1. Will NodeJs continue to run if there are listeners attached to anything or just the global process object?

Not just global process object. For listener, it depends on whether there are any scheduled work left (whether the listener would be possibly triggered).

2. Why will NodeJs not terminate if there are listeners attached ?

JavaScript uses single thread model, and use event loop to process various action logic. If Node.js terminate once the main code is executed, then it can only be used to write very small program. It won't be able to listen user actions / external request etc.

3. Is this a behavior only for the data event ? Or do other events also result in the same behavior ?

Other events may also result in the same behaviour, depends on whether that event would trigger scheduled-work.

4. What are the other ways a node process can be kept from terminating ?

Whatever when a event listener is possible-to-be-called-later.

Upvotes: 1

Alan Mroczek
Alan Mroczek

Reputation: 1199

Node exits when it has done its job. If you set event listener it will not terminate because it has still a job to run - your code tells, that it has to listen to some kind of event. So as long as it is any event listener, that is bound to any still present object and can be called, it will continue to run. In case of exit events, node will clean everything for you.

Upvotes: 1

Alexandru Olaru
Alexandru Olaru

Reputation: 7092

1. Will NodeJs continue to run if there are listeners attached to anything or just the global process object ?

this is more related with the fact that process.stdin is creating a socket more exactly net.Socket() which is a duplex stream, both readable and writable, and also this is an EventEmitter class so when you attach a listener to the process.stdin you open the socket and you are waiting to write|read something in the socket.

So the problem here is not the EventEmitter's handler, but more the stream which is waiting for the end event to kill the process.

2. Why will NodeJs not terminate if there are listeners attached ?

Becouse you opened a socket connection, and only a special end event will terminate it. In your case it will terminate when you give the terminate command that will trigger a special end event CTRL+C;

3. Is this a behavior only for the data event ? Or do other events also result in the same behavior ?

For the process.stdin all the events, and other connection types i/o. db connections, http request etc...

4. What are the other ways a node process can be kept from terminating ?

  • Run a synchronous infinite loop.
  • Open a socket and do not close it.

Attached the source code for the process.stdin.constructor by using process.stdin.constructor.toString()

function ReadStream(fd, options) {
  if (!(this instanceof ReadStream))
    return new ReadStream(fd, options);
  if (fd >> 0 !== fd || fd < 0)    throw new errors.RangeError('ERR_INVALID_FD', fd);

  options = util._extend({
    highWaterMark: 0,
    readable: true,
    writable: false,
    handle: new TTY(fd, true)
  }, options);

  net.Socket.call(this, options);

  this.isRaw = false;
  this.isTTY = true;
}

Upvotes: 3

Related Questions