Shai UI
Shai UI

Reputation: 51918

How can a module in node.js maintain state?

I have two different js files that use the same module.

file1.js:

var mod1 = require('commonmodule.js');
mod1.init('one');

file2.js:

var mod2 = require('commonmodule.js');
mod2.init('two');

(both these files file1.js, file2.js are loaded inside my server.js file, they themselves are modules)

now in commonmodule.js:

var savedName;
exports.init = function(name)
{
    savedName = name;
}
exports.getName = function()
{
    return savedName;
}

I noticed that this savedName is always overridden dependent on who set it last.So it doesn't seem to work. How would I get a module to maintain state?

Note: I also tried to set savedName as exports.savedName in the commonmodule.js but it doesn't work either

Upvotes: 14

Views: 20196

Answers (4)

Miguel
Miguel

Reputation: 20633

You can just create a new instance every time the module is required:

commonmodule.js

function CommonModule() {
    var savedName;
    return {
        init: function(name) {
            savedName = name;
        },
        getName: function() {
            return savedName;
        }
    };
}

module.exports = CommonModule;

file1.js

var mod1 = new require('./commonmodule')();
mod1.init('one');
console.log(mod1.getName()); // one

file2.js

var mod2 = new require('./commonmodule')()
mod2.init('two');
console.log(mod2.getName()); // two

Upvotes: 8

Vinz243
Vinz243

Reputation: 9938

You could perhaps remove from cache your module. Like that:

file1.js:

var mod1 = require('commonmodule.js');
mod1.init('one');

file2.js:

delete require.cache[require.resolve(modulename)];

var mod2 = require('commonmodule.js');
mod2.init('two');

But I don't find it very convenient and clean.

But you could also clone it or make a small proxy.

Also you could create classes:

var savedName;
exports.obj = {}
exports.obj.prototype.init = function(name)
{
    savedName = name;
}
exports.obj.prototype.getName = function()
{
    return savedName;
}

Then :

var mod2 = new (require('commonmodule.js'))();
mod2.init('two');

Upvotes: -2

Peter Lyons
Peter Lyons

Reputation: 146014

modules in and of themselves are simple object instances. A single instance will be shared by all other modules (with the caveat that it is loaded via the same path). If you want state, use a class and export a constructor function.

example:

//Person.js
function Person(name) {
    this.name = name;
}

module.exports = Person;

To use it:

var Person = require("./Person");
var bob = new Person("Bob");

Upvotes: 7

JAB
JAB

Reputation: 21089

Modules are not like classes/class functions; by default, mod1 and mod2 will refer to the same module due to caching. To keep track of per-instance state, you'll need a constructor function or something similar inside your module, e.g.

var mod = require('commonmodule.js');
var state = new mod.init('one');

Where init defines the stateful object. You could also have it return an object literal, in which case you wouldn't have to use new (e.g. var state = require('commonmodule.js').init('one');)

(This is assuming you want the module to have other, shared state in addition to the per-instance state; if that is not the case, Peter Lyons' method would be simpler.)

Upvotes: 0

Related Questions