What is good practice when writing a node.js module - node.js

I can't really get a grip on what is considered to be good and bad practice when writing a module for in node.js. Some modules seem to use a lot of exports, while other use just one, etc.
Example:
var self;
var mymodule = function() {
self = this;
this.value1 = something;
this.value2 = somethingElse;
};
module.exports.init = function() {
return new mymodule();
};
mymodule.prototype.functionalityType1 = {
someFunction: function(callback) {
var a = self.value1;
anotherfunction(a, callback);
},
};
mymodule.prototype.functionalityType2 = {
someFunction: function(callback) {
var a = self.value2;
anotherfunction(a, callback);
},
};
var anotherfunction = function(v, callback) {
// do stuff with v
callback(result);
};
Each of the prototypes would contain more than one function obviously.
Would something like this be considered good practice?

It really depends on what sort of module you are writing. Exporting multiple functions works well for utility modules which have multiple methods but little to no internal state to manage. Think something like the fs (file system) module. There are a number of file system methods, but they all pretty much stand alone and there is no shared state.
If you're building a stateful module with multiple methods which operate on state then you should probably just export a constructor and allow the client to create an instance of that object that they can manage. An example of this is the http module which allows you to create a server, and that server has methods which affect its internal state.
If you need to have more than one instance of an object from a module then you really don't have much choice but to export a function which returns an instance of the object.
It's not all that different from frameworks like .NET where you have file system (System.IO) classes which have static methods for standalone operations like verifying a directory exists, or reading the contents of a file and then they have instance classes for classes which maintain state.

Related

What is good pattern to share an object between modules in Nodejs?

My situation is that I'm working with Websocket, and there is only one websocket server and lot of methods need to get data from server and modify things on server, i.e. delete inactive sockets, etc.
Right now I'm simply passing server instance through function calls and wrapper functions which is getting tedious and is error prone to everything (cyclic dependencies, typos, etc)
Importing server instance causes circular dependencies.
Passing them through parameters causes too much interdependence.
Ex:
onConnection -> attaches events
onMessage = msgHanlder(server);
...
then in msgHandler there are multiple events to take care of
onNewMsg = newMsg(server)
onDelete = delete(server)
onRequest = request(server)
It's very functional style programming but it's too much pain.
Create a caching module ( get,set method ) and require this module to manage your state between different modules.
cache.js
let _cache = {};
module.exports = {
"get":function(key){
return _cache[key];
},
"set":function(key,value){
_cache[key] = value;
}
}
a.js
const cache = require('./cache');
const b = require('./b');
cache.set('a','value set in a');
b.invoke();
b.js
const cache = require('./cache');
module.exports = {
"invoke":function(){
console.log("Module A: ",cache.get('a'));
}
}

nodejs referenceerror on nested function calls using async.series and async.until

I'm new to nodejs and trying to learn the basics by rebuilding an existing i2c sensor system.
Got it all running using a named functions and async.series inside a single file. To keep make reusable i now want to create a class which i then can import. unfortunatly i get some errors i don't understand.
class.js
const async = require('async');
const i2c = require('i2c-bus');
class Sensor {
constructor (channel) {
this.channel = channel;
var self = this;
}
openBus (callback) {
bus = i2c.open(self.channel, (err) => {callback()}); // shorted for stackoverflow
}
closeBus (callback) {
bus.close( (err) => {callback()}); //also shorted for better readability
}
connection (callback) {
/* first variation */
async.series([openBus, closeBus], callback);
connection2 (callback) {
/* second variation */
async.series([this.openBus, this.closeBus], callback);
}
}
module.exports = K30;
when i import the class, i can without any problem create a new sensor 'object' and call the functions directly using:
> var Sensor = require('./class.js');
> var mySensor = new Sensor(1);
> mySensor.openBus(foo);
> mySensor.closeBus(bar);
but if i go an try call the wrapper-functions, i get the following errors:
> mySensor.connection(foo);
ReferenceError: openBus is not defined (at 'connection')
> mySensor.connection2(foo);
ReferenceError: self is not defined (at 'openBus')
i believe those errors occure due to my lack of understanding the correct usage of this and self. sadly i can't find any good ead on that topic. any help is highly appreciated.
UPDATE
the solution provided in the first two anwsers was in fact my first approch before starting to use "self" (after some googling [this-that-trick]).
anyways, here is the output/error i get using "this.channel" instead:
> mySensor.connection2(foo);
TypeError: Cannot read property 'channel' of undefined (at openBus)
This is not saved anywhere var self = this; and therefore is lost when the function (constructor is function) ends.
Just remove the above line in constructor and use everywhere the this instead of self.
Its true that this keyword is little tricky in javascript, but if you follow reasonable approach, you should be fine.
You indeed have issue with this and self
Every member inside the class has to be referred by this. If you declare a variable named var EBZ-Krisemendt = "SO user";, to access it, you need to use it with this, eg: console.log(this.EBZ-Krisemendt);
What you need here is
openBus (callback) {
bus = i2c.open(this.channel, (err) => {callback()});
}
and then mysensor.connection2(foo) will work fine.
while i still don't fully understand the reason behind this i fixed my code by getting rid of that "ES6" class definition.
class.js
const i2c = require('i2c-bus');
const async = require('async');
function Sensor(channel) {
let that = this; // make 'this' available in sub-function scope
this.channel = channel;
function openBus(cb) {
// open the bus-connection
bus = i2c.open(that.channel);
}
function closeBus(cb) {
// close the bus-connection
}
function connection(cb) {
async.series([openBus, closeBus], cb);
}
function getReading(cb) {
async.until(
function() {
// loop condition e.g. max tries to get reading
},
function(cb) {
connection(cb); // calling nested synchronous connection-routine
},
function (err) {
// result handling
}
); // end async.until
} // end getReading
return {
getReading: getReading
} // make only 'getReading' available
}
module.exports = {
Sensor: Sensor
} // make 'Sensor' available
in the 'member'-functions i can now use the 'class'-variables of 'Sensor' by accessing them with 'that' (e.g.: 'that.channel')
Detail:
function openBus(cb){
bus = i2c.open(that.channel);
}
if i'd use this instead of that it would only work while calling openBus directly. in my example it's neccessary to call openBus and closeBus in a synchronous manner (for obvious reasons). since async.series is additionally nested inside async.until (sensor might need several tries to response) the scope of this changes. by using that instead i'm able to ignore the scope.
Comment:
since the solution is kinda generally pointing to using nested async-calls inside custom modules i'll slightly alter the titel of the initial question. i'm still hoping for better solutions and/or explanations, so i won't mark my own anwser as accepted yet.

Setting Module Exports to Variable or Not and to Function or Not

What's the point in setting module.exports to a var vs. just exposing it as plain module.exports? Here are 2 ways possible to set it to a variable and then last just setting it to plain old module.exports. I'm trying to understand the use cases for doing it the various ways and also if the first example makes any sense to set it to an object when I'm doing that sort of thing already in my last example.
var board = module.exports = {
doSomething: doSomething()
};
board.initialize = function(){
...
}
doSomethingElse = function(){
}
or
var board = module.exports = function(){
initialize();
}
function initialize(){
...
}
board.doSomethingElse(){
}
or
module.exports = {
doSomething: doSomething()
};
function doSomething(){
...
};
Seems like there are many ways to do the same kind of things but trying to make sense of good patterns and when.
The difference between the first way and second way is that in the first you are exporting an object whereas in the second you're exporting a function. I generally export as a function if I need to inject some dependency into whatever I'm working with.
As for whether or not to assign module.exports to a variable, there is no practical difference between doing it and not doing it. I generally don't as I like to keep it at the bottom of my module as to highlight exactly what is being exported, but you can do it either way. The important thing is to just do it the same way throughout your application.

how to import external library to nodejs

I would like to know how can I import an external library to nodejs.
For example I would like to have phanotmjs library (I know that arelady exist an npm to get phantomjs, but is only an example).
I think that a way was to get the source file of library and include it into a module like that:
module.exports = function (name, cb) {
//source code of library
});
But I think it is a wrong way of doing it.
How can I include an external library to nodejs project to use it inside the project with its functionality?
Thanks
Without exporting, a no elegant way is to copy past the entire library, in the bottom of your node file. nasty you may already thought about it. there is also a bad thing about that. you will not be able to reuse it in all different files.
The other way is to export the files along your workflow every time you need a function. And i think this is ok.
Otherwise to answer that, you can write the export this way:
module.exports = {
removeElementFromArray_Mutate,
hasClass,
hasClass_ONEtest,
removeClassFromAll,
addClass,
removeClass
};
you can do that with node. all of those are normal function declared this way:
function removeClassFromAll(DOMobject, classes){
for(let i = 0; i < DOMobject.length; i++){
removeClass(DOMobject[i], classes);
}
}
function hasClass_ONEtest(DOMElement, classe) {
let allClasses = DOMElement.className.split(/\s+/);
for(let i = 0; i < allClasses.length; i++){
if(allClasses[i].trim() === classe){
return true;
}
}
return false;
}
function hasClass(DOMElement, classes) {
if (typeof classes === 'string') {
return hasClass_ONEtest(DOMElement, classes);
} else { // multiple classes as array
for (let i = 0; i < classes.length; i++) {
if (!hasClass_ONEtest(DOMElement, classes[i])) {
return false;
}
}
return true;
}
}
this way you can write a quick script that parse all the file, and take out the definitions of the functions, if you can't do it manually. You can use regex, to speed up that. you need two patterns. the first for function name( and the second for name = function(. Hope that was helpful!
the question was more about if there is a way included with nodejs. There is none at the moment. it may be in the future. You may also see this How do I include a JavaScript file in another JavaScript file?. It may not help though.
When one requires a module on nodejs, the content of module.exports is returned. So, one can return a function (as you do on your example) or an object, as in
in module.js:
module.exports={
func:function(){ return true; },
val:10,
...
}
So that, in the requiring file, you can:
var m=require('module');
assert(m.func()===true);
assert(10===m.val);
This is explained in the nodejs documentation under Modules
So if you have an external JS library that exposes three functions: a, b, and c, you might wrap them as:
module.exports={
exportedA:lib.a,
exportedB:lib.b,
exportedC:lib.c
};
lib.a=function(){ ... };
lib.b=function(){ ... };
lib.c=function(){ ... };

Namespacing a javascript library, as optional

I'm about to start building a JS library that will have multiple modules. Let's suppose the library is called Library, and two modules will be called One and Two. I'd like for end users to be able to call the library in two different ways:
Library.One.somefunction(params)
or
somefunction(params)
Basically, I want to give the end users the option of including a namespace or not. Is there a good way to do this? Also, is there a good way to do this if I also want to provide a minified version of the library? This library is something that I could end up in Node.js; for now, I'm going to use it myself, but I want to design it in such a way that it's not too hard to turn in to a sharable project in the future.
Any references you can point me to would be great, thanks!
If you're using Node.js you could leverage the CommonJS module system.
math.js (your library)
exports.add = function() {
for (var i = arguments.length; i--;) {
sum += arguments[i];
}
return sum;
};
program.js (someone using it...)
var MyMath = require('math');
console.log(MyMath.add(1, 2)); // 3
// ... in different ways
var add = require('math').add;
console.log(add(1, 2)); // 3
The basic idea behind making a "namespace" optional is to assign the functions to the global scope, which is the window object:
window.somefunction = Library.One.somefunction;
You can write an include function that works similar to other languages:
var include = function (library, p) {
if (!p) {
for (var prop in library) {
if (library.hasOwnProperty(prop)) {
window[prop] = library[prop];
}
}
} else {
window[p] = library[p];
}
};
Then just do, as required:
include(Library.One);
Or use particular functions only:
include(Library.One, 'somefunction');
Warnings:
Executing the functions without the dot notation (One.somefunction) will cause the this keyword to refer to window rather than Library.One. This isn't a problem if you don't use this at all. If you have data to share to between functions then you can do so using closure scope instead of this:
var Library = {};
(function () {
// I'm a closure, I have local scope
var sharedData = "I'm shared but private to this scope";
Library.One = {};
Library.One.funcOne = function () {
alert(sharedData);
};
Library.One.funcTwo = function () {
sharedData += "!";
};
}) ();
Others have well-advised not to make your methods global. This is because once it is global, it is global for all files, and therefore likely to conflict with other code. What you can do is modify the import function above to create a new object, and assign everything to that object before returning it. Then files that need shortcuts to particular libraries can do:
(function () {
var _ = include(Library.One); // This stays within this scope
_.somefunction();
})();
well, i don't know what you mean by "good way".
First of all, the whole purpose of a namespace is to collect variables that are related and not scatter them all around your public namespace.
Personally I wouldn't use such a thing, but you could loop through your namespace's objects and attach them to the window :
for(var i in Namespace)
if(Namespace.hasOwnProperty(i))
window[i] = Namespace[i];
You could do this pretty easily, but are you certain you want to make all the methods global properties?
You could implement it like this (very simplified):
(function( window, undefined ) {
// Your code setting up namespaces
var Library = {One:{},Two:{}};
// function for adding library code to both namespaces.
// Could be modified to accept an Array of functions/names
function addToLibraryOne( id, fn ) {
window[id] = Library.One[id] = fn;
}
// add a function
addToLibraryOne( "somefunction", function( params ) {
// function code
});
window.Library = Library;
})( window );
I'd wonder if you really want to pollute the global namespace like this.
At the very least, I'd make the global properties an option, then only have the function add those if that option is selected.
Well, the second one means that you also want the functions and object and whatever in your modules to be in the global scope. Entirely possible of course, but so against best practices as to be somewhat abhorrent.
For the first part, just declare your Library namespace globally:
var Library = {};
and then start populating it with your modules:
Library.One = {};
Library.Two = {};
and then start adding the functionality to those modules.
(function($) {
var $.froobString = function(s) { .... };
...etc...
})(Library.One);
(Here I've done it as a self-executing anonymous function that passes in Library.One as $.)
To convert all that to globals, have a routine like this:
var convertToGlobals = function(module) {
for (name in module) {
window[name] = module[name];
}
};
convertToGlobals(Library.One)
But then again I'd advise against it.
I might be wrong about this (so this might get downvoted, but I want this evaluated), but I think you are setting up a contradiction with the requirements
1) I want to use namespaces
2) I want to be able to access namespace functionality without the namespace.
basically 2 is "I dont want namespaces".
For implementation, you could just define a bunch of functions globally that route into the namespace, but then why have the namespace to begin with?

Resources