Right way of writing and loading modules in node.js? - javascript

Currently, I write node.js modules like this:
//MyModule.js
function MyModule() {
...somecode
}
MyModule.prototype.someFunc = function() {...}
module.exports = MyModule
However, when I need to use the module, I have to write something like this:
//main.js
var MyModule = require('MyModule');
var myModule = new MyModule();
This seems terribly ugly. Isn't there some way to do something like this
//main.js
var myModule = require('MyModule').new();
Am I doing something wrong?

quick hack for something not ugly
module.js
function MyModule() {
console.dir('constructor');
}
module.exports = MyModule;
app.js
Function.prototype.new = function () {
return new this();
};
var MyModule = require('./module.js').new(); // 'constructor'

If your module consists solely of functions, it may not need to be created as an instance - just define your module as being an object filled with functions. Like so:
var MyModule = {
prepareHtmlContent: function() {
},
autoLoadActionInitiatorFunctions: function() {
}
};
The reason I suggest this is that you've referred to your object as 'MyModule'. If your intent is specifically to use it as a 'Class', and instantiate separate copies of it when they're needed, then you're doing it the correct way.

Here is what I use
(function(module) {
module.myFunction = function() {
}
module.createSomeObj = function() {
return {
foo: 1,
bar: 'bar'
};
}
}(module.exports));
Usage
var myModule = require('./myModule');
myModule.myFunction();
var myObject = myModule.createSomeObj();

Related

Passing a parameter to a called module

My app.js contains:
var m1 = require("./m1");
m1.f1(...);
My m1.js contains:
var m1 = module.exports = {};
m1.f1 = function(...) { };
I would like to pass somevariable when loading m1 from app.js:
var m1 = require("./m1")(somevariable);
How can I write m1.js so that the function definition of m1.f1 can access somevariable?
If you want to be able to do this:
var m1 = require("./m1")(somevariable); // it is equivalent to var m = require("./m1"); and then m(someVariable); so m (the exports of the module m1.js) should be a function
then module.exports in m1.js should be a function:
// m1.js:
module.exports = function(theVariable) {
// use variable then return the following object:
return {
f1: function() { /* ... */ }
};
}
So now you can use the module in app.js like this:
// app.js:
var m1 = require("./m1")(someVariable);
m1.f1(/* ... */);
module.exports is the value that will be returned by the call to require when loading the module.
// app.js
require("./m1")(somevar);
// m1.js
module.exports = function(param) {
return "something";
}
The answer above by Ibrahim makes sense if you want to call m1 as a function. What it seems to me, though, is that your use case would be better served by using a JS class.
That way, you can import 'm1' the regular way with require('m1') and then create an instance of M1 with new m1(<whatever you want to pass in>);
Now when you want to call M1, just use m1.f1()
To support classes, your M1 should look something like:
export default class m1 {
constructor(param1, param2) {
this.param1 = param1;
this.param2 = param2;
}
f1() {
do whatever with params here
}
}
The biggest benefit of this is readability. Now when someone (or you) looks at your code, they will see where this input is coming from. Otherwise, it can be hard to track down where the params are coming from. Especially as your code gets more complex.

browserify modules and notation

Suppose I have a MyViewModel like this:
// MyViewModel.js module
function MyViewModel() {
};
exports.MyViewModel = MyViewModel;
And main.js using it:
// main.js
var MyViewModel = require('./MyViewModel');
var vm = new MyViewModel.MyViewModel(); // akward
it's weird to have new MyViewModel.MyViewModel().
What's the best way to handle this?
Found the answer myself:
// MyViewModel.js module
module.exports = function MyViewModel() {
};

Execute NodeJS module with specific variables injected

I have a module like below
'use strict';
var val = GlobalVariable.someMethod();
...
...
module.exports = myExportedClass;
I am calling it with require('./myModule');. But would like to know if GlobalVariable can be dynamically injected.
I have tried this method, though I know that this does not work :)
(function(GlobalVariable) {
require('./myModule');
})(SomeOtherGlobalVariable);
So it did not, because module will execute in different scope. Is there any other way where I can pass my own version of GlobalVariable when using require.
Yes, it can be injected. Do something like the following:
module.exports = function(injectedObject) {
return {
doSomething: function() {
return injectedObject.something();
}
}
};
you can pass you variable as an argument when requiring it
yourvariable="value";
var file = require('./myModule')(yourvariable);
or can pass it separately, as file now contain function reference of module.exports
yourvariable="value";
var file = require('./myModule');
file(yourvariable)
your module will look like as:
module.exports = function(yourVaraible) {
yourVaraible.myfunction = function() {
};
return yourvariable;
};

How do you use class based OOP JavaScript in the browser?

I've been converting my procedural JS functions into a class and now I'd like to know when to instantiate it.
Here is my class:
MyProject = function() {};
MyProject.prototype.myProperty = "10";
MyProject.prototype.myMethod = function (value) {
// do something
}
Here is my HTML page:
<script src="javascriptfilesdirectory/MyProject.js"/>
<script>
function initialize() {
myProject = new MyProject();
}
</script>
<body onload="initialize()" >
My question is do I intialize it on page load and create a local variable as shown above or do I initialize it in the JS class file?
Here is my JS file:
MyProject = function() {};
MyProject.prototype.myProperty = "10";
MyProject.prototype.myMethod = function (value) {
// do something
}
myProject = new MyProject();
Also, I'm talking in general and in this case it's a singleton. I only want one copy of it in use.
If you really want it as a singleton, you can do it easier than that, something like:
var myProject = new (function() {
this.myProperty = "10";
this.myMethod = function(value) { }
})();
Your "class" is only defined long enough to assign it once, since you're never going to instantiate a second copy.
For a non-singleton, I tend to follow the pattern found on the TypeScript page:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var greeter = new Greeter("world");
Also, I'm talking in general and in this case it's a singleton. I only want one copy of it in use.
In that case, just directly create the object:
var myProject = {
myProperty: "10",
myMethod: function() { ... }
};
When and where you create the object doesn't matter, as long as you have access to it when and where you need it.

JS turning a function into an object without using "return" in the function expression

i have seen in a framework (came across it once, and never again) where the developer defines a module like this:
core.module.define('module_name',function(){
//module tasks up here
this.init = function(){
//stuff done when module is initialized
}
});
since i never saw the framework again, i tried to build my own version of it and copying most of it's aspects - especially how the code looked like. i tried to do it, but i can't seem to call the module's init() because the callback is still a function and not an object. that's why i added return this
//my version
mycore.module.define('module_name',function(){
//module tasks up here
this.init = function(){
//stuff done when module is initialized
}
//i don't remember seeing this:
return this;
});
in mycore, i call the module this way (with the return this in the module definition):
var moduleDefinition = modules[moduleName].definition; //the callback
var module = moduleDefinition();
module.init();
how do i turn the callback function into an object but preserve the way it is defined (without the return this in the definition of the callback)?
you have to use:
var module = new moduleDefinition();
and then you're going to get an object.
Oh, and maybe you want to declare init as this:
this.init = function() {
Cheers.
How about something like this (I can only assume what mycore looks like):
mycore = {
module: {
definitions: {},
define: function(name, Module) {
this.definitions[name] = new Module();
this.definitions[name].init();
}
}
};
mycore.module.define('module_name', function () {
// module tasks up here
this.init = function () {
// init tasks here
console.log('init has been called');
};
});
I don't know what framework you're using or what requirements it places on you, but Javascript alone doesn't require a function to return anything, even a function that defines an object. For example:
function car(color) {
this.myColor = color;
this.getColor = function() {
return this.myColor;
}
//note: no return from this function
}
var redCar = new car('red');
var blueCar = new car('blue');
alert(redCar.getColor()); //alerts "red"
alert(blueCar.getColor()); //alerts "blue"
One more alternative http://jsfiddle.net/pWryb/
function module(core){this.core = core;}
function Core(){
this.module = new module(this);
}
Core.prototype.modules = {};
module.prototype.define = function(name, func){
this.core.modules[name] = new func();
this.core.modules[name].name = name;
this.core.modules[name].init();
// or
return this.core.modules[name];
}
var myCore = new Core();
var myModule = myCore.module.define('messageMaker', function(){
this.init = function(){
console.log("initializing " + this.name);
}
})
myModule.init();

Categories

Resources