12

A simple node program with a single line of code quits immediately after running all the code:

console.log('hello');

However, an http server program listening on a port does not quit after executing all code:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

So my question is, what made this difference? What made the first program quit after executing all code, while the second program continue to live?

I understand in Java, the specification says that when the last non daemon thread quits, the JVM quits. So, what is the mechanism in the nodejs world?

jww
  • 97,681
  • 90
  • 411
  • 885

3 Answers3

15

[...] what made this difference? What made the first program quit after executing all code, while the second program continue to live?

The 2nd program .listen()ed.

Node's mechanism is the event loop and a node process will generally exit when:

  • The event loop's queue is empty.
  • No background/asynchronous tasks remain that are capable of adding to the queue.

.listen() establishes a persistent task that is indefinitely capable of adding to the queue. That is, until it's .close()d or the process is terminated.

A simple example of prolonging the 1st application would be to add a timer to it:

setTimeout(function () {
    console.log('hello');
}, 10000);

For most of that application's runtime, the event queue will be empty. But, the timer will run in the background/asynchronously, waiting out the 10 seconds before adding the callback to the queue so that 'hello' can be logged. After that, with the timer done, both conditions are met and the process exits.

Community
  • 1
  • 1
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • I missed that in my answer and was looking for a right place in node.js source - is it in `net.Server`? I mean, where in the node.js source is this "persistent task"? **edit** I guess I could rephrase my question: how to implement this behaviour on my own? Do I need to do I/O? – kamituel Oct 31 '13 at 06:48
  • Thanks for explaining the two conditions for node to quit. That makes sense to me. Would you please show me some code demostrating how to manipulate the event/task queue? –  Oct 31 '13 at 06:59
  • @kamituel's question is exactly my question. I actually want to write my own service lifecycle management server. I'm hoping to understand what is the proper way to maintain the main event loop. –  Oct 31 '13 at 07:01
  • 1
    @kamituel Well, it's not documented with those words, exactly. But, yeah, under `net.Server` it mentions "[*Begin accepting connections*](http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback)," suggesting continuation. – Jonathan Lonowski Oct 31 '13 at 07:02
  • 1
    `setTimeout` and `setInterval` adds an event handler to the event queue. In plain js they're the lowest level interface to the event queue. However, node.js implements event emitters. So in addition to the timeout functions you can also implement your own events by inheriting from `EventEmitter` and node will enter the event loop if you then use your custom event. – slebetman Oct 31 '13 at 07:17
  • @JonathanLonowski: Also note that your comment is a bit misleading since events have nothing to do with multi-threading. It's just that to get data into and out of threads, processes and i/o you'd need to use events. – slebetman Oct 31 '13 at 07:18
  • Ah... you're right about EventEmitter. Should have noticed that myself :). With regards to "altering" the event loop. If you listen carefully to the OP and kamituel then you'd notice that `setInterval` is exactly the kind of "altering" of the event loop that they're looking for. – slebetman Oct 31 '13 at 07:28
0

Node.js keeps track of active event listeners. As soon as there are no active event listeners left the Node.js program terminates.

The Hello world -program does not start any event listeners and therefore terminates after the source code has been executed.

The HTTP server program behaves differently. It creates a server and binds it to a port. By doing that it registers a handler to be invoked whenever a new HTTP connection is established. When the end of the program code is reached there's one active event listener present and the program keeps running.

You could terminate the server program by issuing server.close() after a while.

pspi
  • 11,189
  • 1
  • 20
  • 18
-1

More of a comment than an answer, but its not related to a listening server process. As Jonathan Lonowski stated, its based on an event loop. For example, this is from Jim Wilson's Node.js the Right Way:

// watcher.js - watches a text file for changes.
const fs = require('fs');

fs.watch('target.txt', function() {
    console.log("Target.txt just changed!");
});

console.log("Watching target.txt");

Its invoked with node --harmony watcher.js.

It does not exit; and it requires a CTRL+C.

jww
  • 97,681
  • 90
  • 411
  • 885