Howardism Musings from my Awakening Dementia
My collected thoughts flamed by hubris
Home PageSend Comment

Node.js Modules

Node.js has a very coherent approach to structuring code. I didn't realize until I was "into" my first project that Node modules follow the Singleton Pattern. Since this wasn't obvious from the Node.js documentation, I thought I would explain it.

Suppose a.js wants to call a function in b.js, you can write something like:

var b = require('b');  // NB: .js is optional
b.callIt();

Unlike JavaScript on the client, variables in Node do not have global scope. This means that b.js has to export the functions that a.js could call:

function someFunction() {
  // … some code …
}
exports.callIt = someFunction;

You could also make this a bit smaller:

exports.callIt = someFunction() {
  // … some code …
};

However, I don't care much for this optimization since most JavaScript IDEs do not show the function in the Code Outline panel. The other advantage of the first approach is that you can give your functions descriptive names that may be different from how the caller would use them.

Module Scope

First time some code requires a module, it is executed. When another piece of code requires that same module, it isn't re-run. While this is efficient, it also means that only one module instance exists in the application.

Why is this important?

Consider the following code:

var counter = 0;

function getID() {
    return ++counter;
}
exports.id = getID;

The variable, counter, is in the module's scope meaning that other functions in the module can access it, but since it isn't exported, no one else can.

But since only one module instance is available per application, this is effectively the Singleton Pattern.

Advantage of this Singleton Pattern

Some of my modules may require a lot of configuration or initialization. No problem. You can just write that could outside of a function, and it is executed once.

Normally, I create and call an init function:

function init() {
  // Lots of setup work here.
}

init(); // Initialize the module

Disadvantage of this Singleton Pattern

All variables inside a module are essentially shared with the rest of your application (hidden, but still shared). This may not be what you want. In this case, you need create a JavaScript class:

function Foobar(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;

this.sum = function() {
  return this.x + this.y + this.z;
};
}

exports.getFoobar = function(a, b, c) {
    return new Foobar(a, b, c);
};

The require function in Node can be chained, which is useful when you only need one function out of it.

var foo = require('foobar').getFoobar(1,3,7);
Tell others about this article:
Click here to submit this page to Stumble It