How do you modify a nodejs module variable? - javascript

(This is probably a very silly question since I'm just beginning with nodejs, nevertheless I can't understand how this works. Let me know what is missing in my question, I'll correct.)
I'm trying to use the npm package likely.
in my server.js file I have thus written this
var Recommender = require('likely');
in likely.js you can find variables like these:
var DESCENT_STEPS = 5000; // number of iterations to execute gradient descent
var ALPHA = 0.0005; // learning rate, should be small
I would like to modify these variables inside my server.js file.
I believe the way to do that is adding this after the require()
Recommender.DESCENT_STEPS = 9999999999;
but that doesn't seem to change the value that is defined in likely.js and that is actually used by the model. (by running the model I can see it doesn't work since so much steps should take forever and the processing time doesn't change at all)
Can I only do this by modifying likely.js?

You cannot modify them programmatically because likely.js only uses the local variable values instead of the current value of the exported versions of the same variables. So if you wanted to change those values you currently would need to edit likely.js. You might want to submit a pull request to that project's repository that makes the code use the exported value (e.g. module.exports.DESCENT_STEPS) instead.

You need to publicize these variables to be viewable by server.js.
var object = {
DESCENT_STEPS = 5000;
ALPHA = 0.0005;
}
module.exports = object;
Now it can be viewed and modified in server.js.
Recommender.ALPHA = 'new value';

Related

Difference between require('module')() and const mod = require('module') mod() in node/express

I have two files: server.js and db.js
server.js looks as such:
...
const app = express();
app.use('/db', db());
app.listen(3000, () => {
console.log('Server started on port 3000')
});
...
and db.js as such:
...
function init() {
const db = require('express-pouchdb')(PouchDB, {
mode: 'minimumForPouchDB'
});
return db;
}
...
This works just fine, and I am able to reach the pouchdb http-api from my frontend. But before, I had const PouchDBExpress = require('pouchdb-express'); in the top of db.js, and the first line in init() looked like this; const db = PouchDBExpress(PouchDB, {. This gave an error in one of the internal files in pouchdb saying cannot set property query on req which only has getters (paraphrasing).
So this made me copy the exaples from pouchdb-servers GitHub examples which requires and invokes pouched-express directly, and everthing worked fine. Is there an explanation for this? I'm glad it works now, but I'm sort of confused as to what could cause this.
The only difference between:
require('module')()
and
const mod = require('module');
mod();
is that in the second case, you retain a reference to the module exports object (perhaps for other uses) whereas in the first one you do not.
Both cases load the module and then call the exported object as a function. But, if the module export has other properties or other methods that you need access to then, obviously, you need to retain a reference to it as in the second option.
For us to comment in more detail about the code scenario that you said did not work, you will have to show us that exact code scenario. Describing what is different in words rather than showing the actual code makes it too hard to follow and impossible to spot anything else you may have inadvertently done wrong to cause your problem.
In require('module')(), you don't retain a reference of the module imported.
While in const mod = require('module'); mod(), you retain a reference and can use the same reference later in your code.
This problem might be due to some other reason like -
Are you using a some another global instance of the db, and your code works in the given case as you are making a local instance
Some other code dependent scenario.
Please provide more details for the same

Can I export/require a module in Node.js to be used without a var holding its objects?

I am creating my own error library to have a custom catalog of specific and well documented errors to return on my API. I am doing something like this:
module.exports = CError;
function CError () {
}
// CUSTOM ERROR TYPES
CError.EmptyParamError = createErrorType(...);
CError.InvalidFormatError = createErrorType(...);
A sample of how I use my custom error types right now:
CError = require('cerror');
if(!passwd)
callback(new CError.EmptyParamError(passwd, ...));
I will use this errors through my entire project and I wish to have a cleaner code like this: (without the CError reference)
if(!passwd)
callback(new EmptyParamError(passwd, ...);
Is there a way to export the module or to require it that allows me to do this?
I googled without finding any answer, I also checked all this interface design patterns for Node.js modules but no one applies.
You can set it as a global, though as always when using globals, beware of the side-effects.
EmptyParamError = createErrorType(...);
That's it. Just leave off the var keyword, and don't set it as a property.
If it's only one or two types, you can skip the CError variable like this:
var EmptyParamError = require('cerror').EmptyParamError;
if(!passwd)
callback(new EmptyParamError(passwd, ...));
If you have multiple types in a single file, there will be multiple require('cerror') statements, but I believe there's no significant performance hit there because (if I understand correctly) Node will cache it the first time.

Nodejs: Global variables across multiple files

I have written my code across several files for my node server.
If I have a file, say basket.js:
var Basket = {
fruits : 0,
addFruit : function() {
fruits++;
},
removeFruit : function() {
fruits--;
},
printFruit : function() {
console.log(this.fruits);
}
}
module.export = Basket;
And I have another file called give.js:
var Basket1 = require("./basket.js");
Basket1.addFruit();
Basket1.printFruit();
And another file called take.js:
var Basket2 = require("./basket.js");
Basket2.removeFruit();
Basket2.printFruit();
Will both files write into the same instance of Basket?
In other words, will they both have control over the property, fruits?
Does node manage race conditions on its own? i.e. if two commands to modify fruit come in at the same time from add and sub, does node know how to handle it?
If I want to make a way in which two files can look at a singleton at the same time and access it, is this the way to go?? Or how else does one do it?
Yes, they will access the same object.
Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.
– Modules docs
No, node does not manage race conditions on its own, because race conditions will not be caused by node itself. Node is single-threaded and thus no code can be executed at the same time as other code. See for example this answer for some more explanation.
I'm a beginner but I think the correct syntax is module.exports not modules.export - if you may correct so that people don't wonder why it does not work like I just did :)

Node.js global variable property is purged

my problem is not about "memory leakage", but about "memory purge" of node.js (expressjs) app.
My app should maintain some objects in memory for the fast look-up's during the service. For the time being (one or two days) after starting the app, everthing seemed fine, until suddenly my web client failed to look-up the object bacause it has been purged (undefined). I suspect Javascript GC (garbage collection). However, as you can see in the psedu-code, I assigned the objects to the node.js "global" variable properties to prevent GC from purging them. Please give me some clue what caused this problem.
Thanks much in advance for your kind advices~
My node.js environments are node.js 0.6.12, expressjs 2.5.8, and VMWare cloudfoundry node hosting.
Here is my app.js pseudo-code :
var express = require("express");
var app = module.exports = express.createServer();
// myMethods holds a set of methods to be used for handling raw data.
var myMethods = require("myMethods");
// creates node.js global properties referencing objects to prevent GC from purging them
global.myMethods = myMethods();
global.myObjects = {};
// omited the express configurations
// creates objects (data1, data2) inside the global.myObjects for the user by id.
app.post("/createData/:id", function(req, res) {
// creates an empty object for the user.
var myObject = global.myObjects[req.prams.id] = {};
// gets json data.
var data1 = JSON.parse(req.body.data1);
var data2 = JSON.parse(req.body.data2);
// buildData1 & buildData2 functions transform data1 & data2 into the usable objects.
// these functions return the references to the transformed objects.
myObject.data1 = global.myMethods.buildData1(data1);
myObject.data2 = global.myMethods.buildData2(data2);
res.send("Created new data", 200);
res.redirect("/");
});
// returns the data1 of the user.
// Problem occurs here : myObject becomes "undefined" after one or two days running the service.
app.get("/getData1/:id", function(req, res) {
var myObject = global.myObjects[req.params.id];
if (myObject !== undefined) {
res.json(myObject.data1);
} else {
res.send(500);
}
});
// omited other service callback functions.
// VMWare cloudfoundry node.js hosting.
app.listen(process.env.VCAP_APP_PORT || 3000);
Any kind of cache system (whether is roll-your-own or a third party product) should account for this scenario. You should not rely on the data always being available on an in-memory cache. There are way too many things that can cause in-memory data to be gone (machine restart, process restart, et cetera.)
In your case, you might need to update your code to see if the data is in cache. If it is not in cache then fetch it from a persistent storage (a database, a file), cache it, and continue.
Exactly like Haesung I wanted to keep my program simple, without database. And like Haesung my first experience with Node.js (and express) was to observe this weird purging. Although I was confused, I really didn't accept that I needed a storage solution to manage a json file with a couple of hundred lines. The light bulb moment for me was when I read this
If you want to have a module execute code multiple times, then export a function, and call that function.
which is taken from http://nodejs.org/api/modules.html#modules_caching. So my code inside the required file changed from this
var foo = [{"some":"stuff"}];
export.foo;
to that
export.foo = function (bar) {
var foo = [{"some":"stuff"}];
return foo.bar;
}
And then it worked fine :-)
Then I suggest to use file system, I think 4KB overhead is not a big deal for your goals and hardware. If you familiar with front-end javascript, this could be helpful https://github.com/coolaj86/node-localStorage

Setting an environment variable in javascript

How can I set an environment variable in WSH jscript file that calls another program? Here's the reduced test case:
envtest.js
----------
var oShell = WScript.CreateObject("WScript.Shell");
var oSysEnv = oShell.Environment("SYSTEM");
oSysEnv("TEST_ENV_VAR") = "TEST_VALUE";
oExec = oShell.Run("envtest.bat", 1, true);
envtest.bat
-----------
set
pause
I expect to see TEST_ ENV _VAR in the list of variables, but it's not there. What's wrong?
edit:
If someone can produce a working code sample, I'll mark that as the correct answer. :)
The problem is not in your code, but it is in execution of the process. The complete system variables are assigned to the process which is executed. so, your child process also had the same set of variables.
Your code-sample works good. It adds the variable to the SYSTEM environment.
So, you need to set the variable not only for your system but also for your process.
Here's the code.
var oShell = WScript.CreateObject("WScript.Shell");
var oSysEnv = oShell.Environment("SYSTEM");
oSysEnv("TEST1") = "TEST_VALUE";
var oSysEnv = oShell.Environment("PROCESS");
oSysEnv("TEST1") = "TEST_VALUE";
oExec = oShell.Run("envtest.bat", 1, true);
Once you created the system variable.
It will assign the newly created variable for the current process. So, your child process can get that variable while the "SET" command executed.
Sorry for my bad-english.
There are 4 "collections" (System, User, Volatile, and Process) you probably want Process if you just need a child process to see the variable
You are getting the system environment variables. I suspect you simply don't have permission to modify them; you could try changing this to the user environment variables.
Also I don't know whether the argument to Environment() is case-sensitive or not. MS's documentation uses "System" instead of "SYSTEM". Might make a difference but I don't know for sure.

Categories

Resources