exebook
exebook

Reputation: 33900

Node.js double call to require()

//lib.js
var opt = 0

exports.set = function(arg) {
   opt = arg
}

exports.prn = function() {
   console.log(opt)
}


///prog.js
var lib = require('./lib')
var lib2 = require('./lib')
lib.set(222)
lib2.set(333)
lib.prn()
lib2.prn()

prog.js will output: 333 333

but I need it to output: 222 333

In ohter words, opt must be unique to variable lib and to variable lib2. How to achieve that?

Upvotes: 2

Views: 1540

Answers (5)

exebook
exebook

Reputation: 33900

Add this line as first line of your lib.js

delete require.cache[__filename]

now your module becomes in a separate namespace each time you require it.

Upvotes: 0

Mithun Satheesh
Mithun Satheesh

Reputation: 27855

Adding to Bergi's answer, You may also try it like

// prog.js
var lib = require('./lib')(),
lib2 = require('./lib')();
lib.set(222)
lib2.set(333)
lib.print()
lib2.print()

// lib.js
module.exports = function constr() {
    var opt = 0

    return { set : function(arg) {
       opt = arg
      },
      print : function() {
       console.log(opt)
      }
    }

};

Upvotes: 1

Krasimir
Krasimir

Reputation: 13529

That's because normally nodejs caches its modules which are got via require. You may use the following helper:

// RequireUncached.js
module.exports = function(module) {
    delete require.cache[require.resolve(module)]
    return require(module);
}

and the usage of the helper:

var requireUncached = require('RequireUncached.js');
requireUncached("./lib"); 

Have in mind that this approach is considered as bad practice and should not be used. I'll suggest to wrap your logic into a function, require the module and call the function. So, every time you get a new instance.

Upvotes: 5

Bergi
Bergi

Reputation: 664538

require will not load scripts multiple times, but always yield the same instance.

If you need different environments, make your module a constructor function that allows to be instantiated multiple times. Store opt on each object for that instead of in the (global) module scope.

// lib.js
module.exports = function constr() {
    var opt = 0
    this.set = function(arg) {
       opt = arg
    };
    this.print = function() {
       console.log(opt)
    };
};

// prog.js
var lib = require('./lib'),
    inst1 = new lib(),
    inst2 = new lib();
/* or short:
var inst1 = new require('./lib')(),
    inst2 = new require('./lib')(); */
inst1.set(222)
inst2.set(333)
inst1.print()
inst2.print()

Upvotes: 4

tadman
tadman

Reputation: 211590

The way the NodeJS module system works, the output is correct and your expectations contradict the design principle here.

Each module is loaded once and only once, and subsequent calls to require simply return the reference to the pre-existing module.

Maybe what you need to do is create a class you can create one or more instances of instead of using module-level globals.

Upvotes: 1

Related Questions