Access to object in module - javascript

Im doing some logic which parse json data to object and I want to expose in some module specific object outside that other module can use,
I try with the following which doesnt work,any other idea?
var jsonObject;
module.exports = {
parse: function () {
//here I do the parsing
....
jsonObject = JSON.parse(res)
,
//here I want to expose it outside
jsonObj:jsonObject
}

If you are trying to expose the entire object, you build it like you would any other JavaScript object and then use module.exports at the end :
MyObj = function(){
this.somevar = 1234;
this.subfunction1 = function(){};
}
module.exports = MyObj;
If you just want to expose certain functions, you don't NEED to build it like an object, and then you can export the individual functions :
var somevar = 1234;
subfunction1 = function(){};
nonExposedFunction = function(){};
module.exports = {
subfunction1:subfunction1,
somevar:somevar
};

you simply assign the result of JSON.parse to this.jsonObj:
module.exports = {
parse: function (res) {
this.jsonObj = JSON.parse(res);
}
};
Using this.jsonObj you are exposing the JSON object to the outside and you can use your module in this way:
var parser = require('./parser.js'),
jsonString = // You JSON string to parse...
parser.parse(jsonString);
console.log(parser.jsonObj);

Related

How to access object.prototype methods from another file using module.exports?

If I want to use an object and its methods in another file, how would I set up my module.exports?
Object:
var Object = function ()
{
...
}
Object.prototype.foo = function (param)
{
...
}
Module.export:
module.exports = {
Object : Object
}
or
module.exports = {
Object : Object,
foo : Object.prototype.foo
}
?
A few ways of doing this but if you're trying to access prototype methods from your other file, then you'll need to instantiate your constructor,
something like:
For ex:
// lib.js
var YourThing = function () {
}
YourThing.prototype.someMethod = function () {
console.log('do something cool');
}
module.exports = YourThing;
// index.js
var YT = require('./lib.js');
var yourThing = new YT();
yourThing.someMethod();
module.exports = Object;
This will export your Object as a Module.
If your object is not renewed in your app, the best way to use it as an executed function with late binding of its prototype methods
const _ = require('lodash')
var Object = function ()
{
..
_.bindAll(this); // at last bind all methods. this way you won't miss a method
}
Object.prototype.foo = function (param)
{
...
}
module.exports = new Object();
then you can call the functions like,
const myObj = require('./object-file')
myObj.myMethod();
If you need reusable component,
module.exports = Object;
const _obj = require('./object-file'); // you can call this way anywhere in any function and for every require, it creates a new object.
var object = new _obj();
_obj.anyMethod();

Export function first and object subsequently

I have a custom module and would like to provide a method to initialize it on first require, but directly return an object on subsequent requires.
But the module gets cached when first required and therefore subsequent requires still return the init function instead of returning obj directly.
server.js:
var module = require('./module.js');
var obj = module.init();
console.log('--DEBUG: server.js:', obj); // <-- Works: returns `obj`.
require('./other.js');
other.js:
var obj = require('./module.js');
console.log('--DEBUG: other.js:', obj); // <-- Problem: still returns `init` function.
module.js:
var obj = null;
var init = function() {
obj = { 'foo': 'bar' };
return obj;
};
module.exports = (obj) ? obj : { init: init };
How can I work around that problem? Or is there an established pattern for achieving such?
But I would like to keep obj cached, because my real init does some work I would rather not do on every require.
There are some ways to clear the require cache. You may check here node.js require() cache - possible to invalidate?
However, I think that this is not a good idea. I'll suggest to pass the module which you need. I.e. initialize it only once and distribute it to the other modules.
server.js:
var module = require('./module.js');
var obj = module.init();
require('./other.js')(obj);
other.js:
module.exports = function(obj) {
console.log('--DEBUG: other.js:', obj); // <-- The same obj
}
module.js:
var obj = null;
var init = function() {
obj = { 'foo': 'bar' };
return obj;
};
module.exports = { init: init };

node.js expose variable to module?

I have read a lot of articles about how to create modules in node.js, and you can use module.exports to expose module internals to the file which includes it.. awesome!
How does this work the other way around? I'll use the following as an example :-)
USER.JS
function User() {
this.property = 'value';
this.doSomething = function() {
var getStuff = mainFileFunction();
// do something with getStuff
}
module.exports = User;
MAIN.JS
var myArray = [];
myArray.push('something');
myArray.push('something else');
mainFileFunction() {
for(thing in myArray) {
return myArray[thing];
}
}
var u = new user();
log(u.property); <--- THIS IS EXPOSED, COOL!
u.doSomething(); <--- This will throw an error because mainFileFunction is not defined in user.js :-(
If I were to move mainFileFunction to the user file, then it still wouldn't work because the myArray array wouldn't be defined... and if I were to move that over too, I wouldn't be able to use it in other functions in main (which I want to) :-)
I'm sorry if I'm missing something really obvious here... What I want is to expose the parts of my choosing from modules I include (module.export works for that) but I also want to expose everything from the main file to all the includes..
or just expose everything to everything? is that totally messy and horrible??
Just to explain what I am trying to do here... I want to have classes defined in separate files, but I want to instantiate a bunch of them as objects in the main file and store them in arrays.. I want the objects to contain methods which can access arrays of the other object types.
Thanks guys! :-)
You can use globals, or have a proper circular dependency (requireing both files), however - this is usually a bad habit which can lead to maintainability problems in the future.
Instead, you can use dependency injection and inject doSomething into your module.
This basically gives you the following for free:
You can test User with a simple mock implementation of doSomething later and verify the correctness of your code
The dependencies of a user are explicit and not implicit, which makes it obvious what a user needs.
I'll provide two implementations, one using constructor dependency injection and one with a module wide setting.
USER.JS
function User(dependentFunction) {
this.property = 'value';
this.doSomething = function() {
var getStuff = dependentFunction();
// do something with getStuff
}
}
module.exports = User;
MAIN.JS
...
var u = new User(mainFileFunction);
u.doSomething(); // this will now work, using mainFileFunction
What happens here is fairly simple, and we know what's going on.
This can also be a module wide setting
USER.JS
function User(depFunc) {
this.property = 'value';
this.doSomething = function() {
var getStuff = depFunc();
// do something with getStuff
}
}
function UserFactory(depFunc){
return function(){
return new User(depFunc);
}
}
module.exports = UserFactory;
MAIN.JS
var getUser = UserFactory(mainFileFunction);
var u = getUser(); // will return a new user with the right function
+1 to Benjamin answer for dependency injection.
I would like to add another way to inject objects in your modules by passing the dependency in the require like require('./module.js')(dependentFunction);
//MAIN.js
var db = function() {
this.rows = [];
this.insert = function(name) {
this.rows.push(name);
console.log('Db: Inserting user with name ' + name);
}
this.getAll = function(){
return this.rows;
}
}
var fakeDb = new db();
var user = require('./user.js')(fakeDb);
user.add('Jhon');
user.add('Rose');
user.list();
and
//users.js
module.exports = function(db) {
return {
add: function(name) {
db.insert(name);
},
list: function() {
var users = db.getAll();
var i = users.length;
console.log('listing users\n-------');
while(i--) {
console.log(users[i]);
}
}
}
}
You should pass mainFileFunction as a parameter to the constructor of user.
USER.JS
function User(mainFileFunction) {
this.property = 'value';
this.doSomething = function() {
var getStuff = mainFileFunction();
// do something with getStuff
}
module.exports = User;
In your main.js use the following
var u = new user(mainFileFunction);
How about moving mainFileFunction to user.js, and have the function accept an array as an argument:
mainFileFunction(array) {
for(thing in array) {
return array[thing];
}
}
And then when you call it from main.js, pass the function your array:
u.doSomething(myArray);

how to use a javascript function to return an object in a node module

I have a problem in which i'm using a file to hold a list of modules and requiring this list in one call in my nodejs server. I want to use the modules in the list in a specific way.
modules.js -
Mods = {
mymodule: require('./mymodule.js')
}
exports.f = function() {
return Mods;
}
index.js -
f = require('./modules.js').f;
f().mymodule.echo("Hello World");
so instead of how i'm using f() now i want to put the name of the module i'm calling directly into the function so I can do things like this:
f = require('./modules.js').f;
f('mymodule').echo("Hello World");
I've tried a number of different experiments but can't get it to work, is it possible to do this in javascript?
Well, if you do this:
var Mods = {
mymodule: require('./mymodule.js');
}
module.exports = function( name ) {
return Mods[name];
};
You can then do:
var f = require( "./modules.js"); //no .f required
f( "mymodule" ).echo( "Hello world");
I would say more ... ^^
var Mods = {
mymodule: require('./mymodule.js');
}
module.exports = function( name ) {
if( !name ) return Mods;
return Mods[name];
};
Edit: I was asked to explain my answer and I'm pleased to do so. The key to the solution is what is called the bracket notation. This term refers to the ability to access a property on an object in JavaScript using a variable. In the code below you can see how the property of the object Mods is accessed using [name] where name is a variable containing the name of the property as a string.
Mods = {
mymodule: require('./mymodule.js');
}
exports.f = function(name) {
return Mods[name];
}

Node.js "require" function and parameters

When I do:
lib = require('lib.js')(app)
is app actually geting passed in?
in lib.js:
exports = module.exports = function(app){}
Seems like no, since when I try to do more than just (app) and instead do:
lib = require('lib.js')(app, param2)
And:
exports = module.exports = function(app, param2){}
I don't get params2.
I've tried to debug by doing:
params = {}
params.app = app
params.param2 = "test"
lib = require("lib.js")(params)
but in lib.js when I try to JSON.stringify I get this error:
"DEBUG: TypeError: Converting circular structure to JSON"
When you call lib = require("lib.js")(params)
You're actually calling lib.js with one parameter containing two properties name app and param2
You either want
// somefile
require("lib.js")(params);
// lib.js
module.exports = function(options) {
var app = options.app;
var param2 = options.param2;
};
or
// somefile
require("lib.js")(app, param2)
// lib.js
module.exports = function(app, param2) { }
You may have an undefined value that you're trying to pass in.
Take for instance, requires.js:
module.exports = exports = function() {
console.log('arguments: %j\n', arguments);
};
When you call it correctly, it works:
node
> var requires = require('./requires')(0,1,2,3,4,5);
arguments: {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5}
If you have a syntax error, it fails:
> var requires = require('./requires')(0,);
... var requires = require('./requires')(0,2);
...
If you have an undefined object, it doesn't work:
> var requires = require('./requires')(0, undefined);
arguments: {"0":0}
So, I'd first check to see that your object is defined properly (and spelled properly when you pass it in), then check that you don't have syntax errors.

Categories