I am trying to implement some functionality into a NodeJS application where some of my controllers (modules) will inherit from one bass module in order to store all common functionality in there. I am having difficulty doing this though and I am unsure why.
Here is what I have so far:
My base module (from which others will inherit from):
var http = require('http');
function ApiBaseController() {
var self = this;
}
ApiBaseController.prototype.makeRequest = function() {
};
module.exports = ApiBaseController;
A child module (that will inherit from the one above:
var APIBaseController = require(__dirname + '/apiBase/ApiBaseController.js'),
inherits = require('util').inherits;
function JustGivingAPI() {
APIBaseController.apply(this);
}
inherits(APIBaseController, JustGivingAPI);
JustGivingAPI.prototype.getAmount = function() {
console.log("here");
};
module.exports = JustGivingAPI;
And the client code which requires the module:
var express = require('express');
var router = express.Router();
var JustGivingController = require('../controllers/api/JustGivingAPI');
var APIObject = new JustGivingControllerObject();
I am trying to implement the aply Javascript method from within the JustGivingAPI module's constructor to inherit the parent module's methods but they don't appear in the returned module.
Can anyone advise me as to where I have gone wrong and if this is a good idea or not?
thanks!
I had the objects the wrong way round in the util.inherits function!
Should be:
util.inherits(JustGivingAPI, APIBaseController);
Related
I am learning ES 6 syntax of classes. I come from a C# background, so I apologize if my terminology isn't correct. Or, if I'm doing something that looks odd.
I'm building a web app as a learning exercise. It's built on Node and Express. I have some routes defined like this:
'use strict';
module.exports = function() {
const app = this;
app.use('/blog', function(req, res) {
console.log('loading blog postings');
res.render('blog', {});
});
app.use('/', function(req, res) {
console.log('looking up: ' + req.path);
res.render('home', {});
});
};
I'm trying to put some viewModels behind these views. So, I have a directory called viewModels. That directory has these files:
index.js
blog.js
home.js
The files currently, probably inaccurately, look like this:
index.js
'use strict';
module.exports = function() {
const HomeViewModel = require('./home);
const BlogViewModel = require('./blog);
};
blog.js
export default class BlogViewModel {
constructor() {
this.title = 'My Blog';
}
}
home.js
export default class HomeViewModel {
constructor() {
this.title = 'Home';
}
}
My thought, was that I could use index.js as a way to define my package or namespace. Then, in my routing code, I could do something like this:
'use strict';
module.exports = function() {
const app = this;
const ViewModels = require('../viewModels/index');
app.use('/blog', function(req, res) {
console.log('loading blog postings');
let viewModel = new ViewModels.BlogViewModel();
res.render('blog', viewModel);
});
app.use('/', function(req, res) {
console.log('looking up: ' + req.path);
let viewModel = new ViewModels.HomeViewModel();
res.render('home', viewModel);
});
};
However, when I attempt this, I get some runtime errors that say "Error: Cannot find module '../viewModels/index'". This implies that I'm not setting up my module properly. But, it looks like I am what am I doing wrong?
Your index.js file is incorrect, you don't export ViewModels from there. Change it to this:
'use strict';
module.exports = {
HomeViewModel: require('./home'),
BlogViewModel: require('./blog')
};
And ... viewModels it's good for C#, but not for Node.js. In node it should be just models, IMO.
Update:
Node.js doesn't completely support all ES6 features, especially new modules declaration: https://nodejs.org/en/docs/es6/. You should use the standard CommonJs module declaration to export your function:
'use strict';
class HomeViewModel {
constructor() {
this.title = 'Home';
}
}
module.exports = HomeViewModel;
Actually, I am not really sure what you want to ask. If I answered wrong stuff, just never mind.
First, the reason why you get error Error: Cannot find module '../viewModels/index' is because you put two dots there. It should be just one dot means start from here. However, I am not sure if this is the problem. I wanted to ask where you put routing code, but I do not have permission to comment yet. (Ahhhh.... Stack overflow you kidding me...)
Second, here is the proper way to export a class in ES6.
For example:
AClass.js
'use strict';
//This module can be used within the class. However, you cannot use it in another file.
const AModule = require('AModule');
//The class name used here just for debug output.
module.exports = class AClass {
constructor(startValue) {
//Not like C#. JavaScript does not define private or public.
this.value = startValue;
}
method(incValue) {
this.value += incValue;
AModule(); //Just show you can use this module within the class;
}
}
main.js
'use strict';
//You need to put a ./ before the path if you are include another module made by yourself.
//You do not need it for a npm module.
const AClass = require('./AClass.js');
//Now you just required the class of the AClass, you still need to new one;
var aClass = new AClass(500);
//After new one, you can call its method.
aClass.method(30);
//You can access its property by a dot;
console.info(aClass.value); //530
This is the 100% work way to create a class in ES6.
Here is detailed documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
Anyways, classes in JavaScripts are just like functions, and a function's prototype will be its methods. new Class() is just create a object, run the function Class with object as this (Same as Class.bind(obj, parameters)), then link the new object's constructor property to the function used.
module.exports = xxx is just make the xxx the value of this module. For instance, if you module.exports = 'Hello'; and console.info(require('module'));, you will get Hello.
I am wondering how I can augument a commonjs module from another module that requires it.
Let's assume that I have three files, two commonjs modules as below:
my-example-module.js
function MyExampleModule(){}
MyExampleModule.prototype = {
bindings: {
some: 'random',
prop: 'values'
}
}
module.exports = MyExampleModule;
another-example-module.js
var MyExampleModule = require('./my-example-module');
function AnotherExampleModule(){}
AnotherExampleModule.prototype = {
getMyExampleModuleBindings: function(){
var module = new MyExampleModule();
return module.bindings;
}
}
module.exports = AnotherExampleModule;
app.js
var MyExampleModule = require('./my-example-module');
var AnotherExampleModule = require('./another-example-module');
//modify?!?
var anotherExampleModule = new AnotherExampleModule();
console.log(anotherExampleModule.getMyExampleModuleBindings());
So what I want to do is have //modify?!? be some kind of code that will alter the original MyExampleModule prototype so when anything else attempts to require MyExampleModule it will get the modified version.
A concrete question would be - what should I replace //modify?!? with so I get logged out the the console with the assumption that my-example-module.js is read only.
{
some: 'random',
prop: 'values',
added: 'binding'
}
If you want to do this in nodejs/iojs, this is pretty simple. When node imports a CommonJS module (let's call it A), it creates an internal object.
When another module (B) wants to load the same module (A), it just gets the reference to that internal object. So if you change something on MyExampleModule in app.js it is also applied to the MyExampleModule in another-example-module.js:
app.js
var MyExampleModule = require('./my-example-module');
var AnotherExampleModule = require('./another-example-module');
//modify:
MyExampleModule.prototype.bindings = {
some: 'random',
prop: 'values',
added: 'binding'
};
var anotherExampleModule = new AnotherExampleModule();
console.log(anotherExampleModule.getMyExampleModuleBindings());
Since you create a new instance of MyExampleModule in another-example-module.js after you call MyExampleModule.prototype.bindings = {...} in app.js, the new instance will already be created with the modified .prototype.
While I haven't tested this in browserify, it certainly works in webpacks implementation of CommonJS as well.
Check out the working example on runnable (app.js is called server.js):
http://code.runnable.com/VZPdN5k65gE5vUIz
Using requires, I’ve split larger class structures down into modules that use other modules within directory. There’s a main file that instantiates the other sub modules. This is an API class with two modules. One that deals with posting data to the endpoint, and the other that holds functions that are helpers to that post module:
define([
'./Post',
'./Helper'
], function (PostModule, HelperModule) {
'use strict';
var module = function () {
this.Post = new PostModule();
this.Helper = new HelperModule();
};
return module;
});
Now I can chain these modules like this:
var foo = new ApiModule();
foo.Post.postToAPI();
foo.Helper.matchAPIactionToEvent();
which is exactly what I want..
BUT, the problem is within the Post.js file, is that it doesn’t know anything about the Helper.js file. So I can’t take advantage of any of those methods. What I would like to do within the Post.js file is to be able to reference the other functions within the same class like so:
define([
'../environment',
'loglevel',
'../utility/Utility',
'jquery'
], function (EnvironmentModule, log, UtilityModule, $) {
'use strict';
var module = function () {
var environment,
utility,
api;
environment = new EnvironmentModule();
utility = new UtilityModule();
this.postToAPI = function (event, payload, callback) {
var apiEndpoint,
requestIdString,
eventAndAction;
apiEndpoint = environment.getEnvironmentPath().API;
requestIdString = utility.String.generateRandomString(32);
/*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
eventAndAction = this.Helper.matchAPIactionToEvent(event);
/*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
payload.event = eventAndAction.event;
payload.action = eventAndAction.action;
payload.requestID = requestIdString;
payload = $.param(payload);
$.post(apiEndpoint + '?' + payload, function (result) {
if (callback) {
callback(result);
}
});
return;
};
};
return module;
});
I figured out a working solution to the this, where I pass '../api/Helper' as one of the array values in the define statement of Post.js; but I don’t want to do that. What I want is to have Post.js be able to access any method from any other modules that are contained within the same directory. That way I don’t have to explicitly define them. It seems wrong to instantiate a new ApiModule() within Post.js. Here’s the directory structure:
Modules/api/Api.js
Modules/api/Post.js
Modules/api/Helper.js
...
I hope that makes sense. Is this possible?
Since you want any of the child modules to access any other child modules, what you could do is pass the parent module as an argument to the constructors of the child modules:
var module = function () {
this.Post = new PostModule(this);
this.Helper = new HelperModule(this);
};
Have the child modules store this information:
var module = function (parent) {
this.parent = parent;
Then use this this.parent to call the methods on other child modules:
eventAndAction = this.parent.Helper.matchAPIactionToEvent(event);
Note that if you would load '../api/Helper' with RequireJS in Post.js as you were thinking of doing, you would not be able to use the same object instance as the one defined on the parent module. You'd have to construct a new object for use in Post.js.
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);
I've been trying to sort out the include of other js files within node.js.
I've read all about the require function and other alternatives and decided to go with the require function (as the code will only ever be used on node.js, not in a browser).
In my code I'm using prototypes to create an 'object' which I later wish to create an instance off.
To get it to work I've been writing code like the following (lets call it vehicle.js):
var util = require('util');
var EventEmitter = require('events').EventEmitter;
module.exports = Vehicle;
util.inherits(Vehicle, EventEmitter);
function Vehicle(options) {
EventEmitter.call(this);
options = options || {};
...
}
Vehicle.prototype._doStartEvent = function(data) {
this.emit('start', data);
};
Vehicle.prototype.testRun = function() {
this._doStartEvent();
};
Then in my main js (lets call it server.js), I have the following:
var test = exports;
exports.Vehicle = require('./vehicle.js');
var remoteVehicle = new test.Vehicle({address: "192.168.1.3"});
remoteVehicle.on('start', function(d) {console.log('started');});
remoteVehicle.testRun();
Now this all works fine, but I do not have a good understanding of what is going on.
My main concern is the use of var test = exports; and then exports.Vehicle = require(...).
I tried just doing something like var vehicle = require(...).Vehicle and var vehicle = require(...), with the goal of just using new Vehicle or similar, but I couldn't get it to work.
Am I forced to use exports and if so why?
Please note I've been using the AR Drone project as an example, the above code is based on how they have done their modules internally. Refer to Client.js and index.js.
result of require is a reference to exports object which is function in your case. Just assign to a variable with the same name as class (or any other) and use as a parameter to new
var Vehicle = require('./vehicle.js');
var remoteVehicle = new Vehicle({address: "192.168.1.3"});
remoteVehicle.on('start', function(d) {console.log('started');});
remoteVehicle.testRun();