Get new object from another class nodejs - node.js

Ok so I have a class that contains
Object JS
var GameServer = require("./GameServer");
var gameServer = new GameServer();
GameServer() contains
GameServer JS
function GameServer() {
// Startup
this.run = true;
this.lastNodeId = 1;
this.lastPlayerId = 1;
this.clients = [];
this.largestClient; // Required for spectators
this.nodes = [];
this.nodesVirus = []; // Virus nodes
this.nodesEjected = []; // Ejected mass nodes
this.nodesPlayer = []; // Nodes controlled by players
}
Now, what im trying to acheive is getting gameServer from ObjectClass
In my class i've tried
new JS
var ObjectClass = require("./ObjectClass");
var gameServer = ObjectClass.gameServer;
But from this way, I won't be able to grab the class GameServer() properties. I'm new to node and im sorry I have to ask this question. I'm currently stuck right now
When I try to grab clients from GameServer
var ObjectClass = require("./ObjectClass");
var gameServer = ObjectClass.gameServer;
gameServer.clients.length;
I get error, clients is undefined. Any way around this?.
I cannot modify GameServer nor Object js.. Basicly im making a script attacthed to a script for extra functionalities.

You are missing the exports of your files so when doing require(file) you're getting and empty object {}..
For gameServer you should be doing something like:
'use strict';
function GameServer() {
// Startup
this.run = true;
this.lastNodeId = 1;
this.lastPlayerId = 1;
this.clients = [];
this.largestClient; // Required for spectators
this.nodes = [];
this.nodesVirus = []; // Virus nodes
this.nodesEjected = []; // Ejected mass nodes
this.nodesPlayer = []; // Nodes controlled by players
}
module.exports = exports = GameServer;
ObjectClass
'use strict';
var GameServer = require("./GameServer");
var gameServer = new GameServer();
exports.gameServer = gameServer;
You need to understand that require cache the value returned by the file, so you would be using a singleton of gameServer.

Related

NodeJS inherits

I've created some scripts and instantiated them on my main script
var eagle1 =new Fleet.F15c(456);
var eagle2 = new Fleet.F15c(123);
var falcon1 = new Fleet.F16(111);
var guardian1 = new Fleet.F14(789);
and have some functions
And now I wanna create a wing - so when the wing is ordered to do something, all the planes assigned to that wing will execute.
I created a 'wing command' script that should have 2 functions that will be called from the main script:
AssignCommand (orderName, planefunction) ->logs the plane function listener to the event emitter of that wing
ExecuteCommand (orderName) -> emits orderName
var EventEmitter = require('events');
var util = require('util');
util.inherits(WingCommand,EventEmitter);
module.exports = WingCommand;
function WingCommand(){
}
But when I created the 1st func
WingCommand.prototype.AssignCommand = function (CommandName , PlaneFunc(data=null)){
this.on(CommandName,PlaneFunc(data));
}
I did not manage figure out the unexpected token on this line
WingCommand.prototype.AssignCommand = function (CommandName , PlaneFunc(data=null)){
I tried some tutorials but did not find a solution
will appreciate your help

Multiple requires of same module seem to affect scope of each successive require

I created the following 3 files:
base.js
var base = {};
base.one = 1;
base.two = 2;
base.three = 3;
base.bar = function(){
console.log( this.three );
};
a.js
var base = require('./base');
base.three = 6;
module.exports = base;
b.js
var base = require('./base');
module.exports = base;
test.js
var test_modules = ['a','b'];
test_modules.forEach( function( module_name ){
require( './' + module_name ).bar();
});
And then run test.js like so:
node ./test.js
It outputs this:
6
6
Why is it that when I set the property 'three' of module 'base' in 'a.js', it then affects the object in 'b.js'?
When you require() a module, it is evaluated once and cached so that subsequent require()s for the same module do not have to get loaded from disk and thus get the same exported object. So when you mutate exported properties, all references to that module will see the updated value.
You are introducing global state for base module.
The module a mutated base and then exported it as well, which means that any further references to base will have an updated value.
It is best demonstrated by the following script inside test.js
var testModules = ['b', 'a'];
testModules.forEach(function(module) {
require('./' + module).bar();
});
Now when you run node test.js, you'll see
3
6
Why?
Because the order of inclusion of the modules changed.
How do I solve this?
Simple, get rid of global state. One option is to use prototypes like so
var Base = function() {
this.one = 1;
this.two = 2;
this.three = 3;
};
Base.prototype.bar = function() {
console.log(this.three);
};
module.exports = Base;
And then, inside a.js
var Base = require('./base');
var baseInstance = new Base();
baseInstance.three = 6;
module.exports = baseInstance;
And inside b.js
var Base = require('./base');
module.exports = new Base();
Now when you run your original test.js, the output should be
6
3

Exporting a new object in Node.js

How can I pass the variables port,host,database into this function?
//myjs.js
var redisCaller = function(port,host,database){
};
module.exports = new redisCaller();
if I do:
var myjs = require('./myjs');
how do I pass those variables?
seems like the only way to do it is like this:
module.exports = function(port,host,database){
return new redisCaller(port,host,database);
}
Change myjs.js to:
module.exports = redisCaller;
Then you can do:
var myjs = require('./myjs')(port,host,database);
You don't.
The way you've set up that code makes it impossible to pass variables in, unless you tweak the require. Which then makes you potentially have to know about the port/host/database in any file you use it in.
Instead, maybe just use an 'init'.
For example, app.js -
var redisCaller = require('./myjs');
redisCaller.init(port, host, database);
And the myjs..
var redisCaller = function(){
this.init = function (port,host,database) {
this.connection = ...
}
this.getConnection = function () {
if(!this.connection) { throw "Need to run init first"; }
return this.connection;
}
};
module.exports = new redisCaller();
Anywhere you need the connection...
var redisCaller = require('./myjs');
var conn = redisCaller.getConnection();
//or
var redisCaller = require('./myjs').getConnection();
It's a bit more code, but at least it's easy to reuse across files.. assuming that was your intention.

Unexpected value for 'this' in express.js instantiated controllers

'this' does not appear to refer to the instantiated budget controller object. Instead it seems to refer to the global object. Does anyone know why this is?
I've defined a budget model. Injected into the controller and I'm attempting to simply generate a random 6 char string when I hit /budgets in my app. Instead this.DEFAULT_SLUG_LENGTH is undefined and I can't figure out why.
This is a dumbed down test case illustrating the issue with 'this'. I have a similar problem when referencing the injected this.budget within another function to query the db based on the slug value.
//models/budget.js
var Schema = require('jugglingdb').Schema;
var schema = new Schema('postgres',{url:process.env.DATABASE_URL});
var Budget = schema.define('budgets',{
total: Number,
slug: String
});
module.exports = Budget;
====================
//controllers/budget.js
function BudgetController (budget) {
this.budget = budget;
};
BudgetController.prototype.DEFAULT_SLUG_LENGTH = 6;
BudgetController.prototype.generateSlug = function (req,res) {
var slug = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < this.DEFAULT_SLUG_LENGTH; i++) {
slug += possible.charAt(Math.floor(Math.random() * possible.length));
}
res.send(slug);
};
module.exports = BudgetController;
===================
//app.js
var express = require('express');
var app = express();
app.use(express.bodyParser());
// models
var Budget = require('./models/budget');
// controllers
var BudgetController = require('./controllers/budget');
var budgetCtrl = new BudgetController(Budget);
// routes
app.get('/budgets',budgetCtrl.generateSlug);
app.listen(process.env.PORT || 4730);
If I manually instantiate the model/controller in the node repl, the generateSlug method works fine. If I restructure my code so that the BudgetController is a function that returns an object {} with methods, that seems to work fine. Is there some issue with my use of prototype/new ?
express takes functions and invokes them without a preceding object, so if you want to use an object method bound to a specific this as an express route handler function, you need to bind it:
app.get('/budgets', budgetCtrl.generateSlug.bind(budgetCtrl));

How to stub out express after you require it with jasmine?

I'm trying to get the code below under test when occurred to me that I already included express at the top of this file. Can you some how monkey patch the express object after it's already loaded?
var express = require('express')
Helper = (function() {
var HelperObject = function(params) {
this.directories = params.directories;
};
HelperObject.prototype.addStaticPath = function(app) {
for(i = 0; i < this.directories.length; i++) {
var static = express.static('/public');
app.use(static);
}
};
return HelperObject;
})();
The problem is that when you create a node module the required modul is bound in the closure of the module and you can't start spying on it cause it isn't visible in your test.
There is Gently where you can override require but it will sprinkle your code with boilerplate test related code.
From the docs:
Returns a new require functions that catches a reference to all
required modules into gently.hijacked.
To use this function, include a line like this in your 'my-module.js'.
if (global.GENTLY) require = GENTLY.hijack(require);
var sys = require('sys');
exports.hello = function() {
sys.log('world');
};
Now you can write a test for the module above:
var gently = global.GENTLY = new (require('gently'))
, myModule = require('./my-module');
gently.expect(gently.hijacked.sys, 'log', function(str) {
assert.equal(str, 'world');
});
myModule.hello();

Resources