javascript: require('events').EventEmitter; - javascript

Why
var EventEmitter = require('events').EventEmitter;
var channel = new EventEmitter();
works, but
var EventEmitter = require('events');
var channel = new EventEmitter();
does not work! Actually, I have another totally different example,
var Currency = require('./currency)
var Cu = new Currency();
works, but
var Currency = require('./currency).Currency;
var Cu = new Currency();
does not work. Here is my currency.js:
function Currency(canadianDollar) {
this.canadianDollar = canadianDollar;
}
module.exports = Currency;
Currency.prototype.cal = function(amount) {
return amount * this.canadianDollar;
}

Because this is the way the API is written. A simplified example of "events" module would look like:
module.exports = {
EventEmitter: function () {
// ...
}
};
In the above case require('events'); would return an Object containing EventEmitter, but require('events').EventEmitter would return the actual EventEmitter function you are likely interested in instantiating.
Thought it would be good to mention that the API designer could indeed export the EventEmitter function directly with module.exports = function () { ... }; however, they decided to leave space for other potentially useful properties of the "events" module.
Edit
Regarding module.exports = EventEmitter; in https://github.com/joyent/node/blob/master/lib/events.js, on the following lines you can find:
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
I suppose that starting from version 0.11 you can run var Emitter = require('events');, but in 0.10.x you are stuck with require('events').EventEmitter.

require returns exactly what you put in module.exports object. So if you have module.exports = Currency; then require returns Currency and if you have exports.Currency = Currency require will return { Currency : Currency } object.
if you want this to work both ways, just do Currency.Currency = Currency; module.exports = Currency. in latest node releases they do like this with EventEmitter

Related

unable to call static function on ES6 class

I have a file called helpers.js in the 'helpers' folder. The contents are like below:
class Helpers {
constructor(config) {
if (this._singleton) {
throw new Error('A singleton has already been created.');
}
this._singleton = this;
}
/**
* Gets the singleton object.
* #returns {Helpers}
*/
static getSingleton() {
return this._singleton;
}
}
module.exports = Helpers;
Then in /helpers/user.js I want to get the helper's singleton instance.
This is my code:
const helpers = require('../helpers').getSingleton();
or
const Helpers = require('../helpers');
const helpers = Helpers.getSingleton();
The error I keep getting is:
TypeError: require(...).getSingleton is not a function
or
TypeError: Helpers.getSingleton is not a function
If I hover over Helpers in VSCode, I get this tooltip
And, whenever I hover over getSingleton() I get this tooltip:
So the path is correct, but it still gives me the errors.
The easiest way to implement the singleton pattern in JavaScript is to just not export the class at all, e.g.
class Helpers {}
let helper;
module.exports = function() {
if (!helper) helpers = new Helpers();
return helper;
};
// loaded with
var helpers = require('../helpers')(); // note the extra () to call it
or even better, since we aren't restricted to Java-like behavior, just skip the function entirely and do
class Helpers {}
module.exports = new Helpers();
// loaded with
var helpers = require('../helpers');
but then if all your module is exporting is a single instance of a class, there's very little reason to use a class in the first place. You might as well do
exports.helperMethodOne = function(){};
exports.helperMethodTwo = function(){};
exports.helperMethodThree = function(){};
// loaded with
var helpers = require('../helpers');
or
module.exports = {
helperMethodOne() {},
helperMethodTwo() {},
helperMethodThree() {},
};
// loaded with
var helpers = require('../helpers');
Your require statement is wrong, but its hard to tell you precisely the right syntax without knowing your environment.
const config = require('/path/to/file');
Is typical. So try:
const Helpers = require('../helpers');
You wrote '../helpers.js' in your screenshot, not '../helpers'
You get the error:
TypeError: require(...).getSingleton is not a function
Because require(...) resolves to something else, like null, and null.getSingleton is not a function.
Also, you cannot reference this meaninfully inside a static context. this ought to only be used for class instances, not static members.
You can do something like this to use it as Singleton.getInstance();
class Singleton {
static instance = new Singleton();
static getInstance = () => Singleton.instance;
constructor() {
throw new Error('Use Singleton.getInstance()');
}
}
module.exports = Singleton;
or even something more sneaky and use it as new Singleton()
class Singleton {
static instance;
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
}
module.exports = Singleton;

Javascript: How to require using const

There's one thing I don't understand about modern Javascript. I see a lot of people discussing whether they should use var, const, or let when requiring new modules. Most people say it's const as their first priority and let second, but I don't see many people who are fan of var. However, this code down below would throw a error TS2451: Cannot redeclare block-scoped variable 'other' error. (Note: This error comes from the Typescript compiler, using the commonjs flag.)
main.js
'use strict';
const A = require('./A.js');
const B = require('./B.js');
// do more stuff
A.js
'use strict';
const other = require('./other.js');
class A {
//...
};
module.exports = A;
B.js
'use strict';
const other = require('./other.js');
class B {
//...
};
module.exports = B;
I'm not sure in which cases it's error-less to use const. It seems that it only works when a module is imported in the main module using const, and then everything else in other modules have var for importing the same module. I'd like to know if I'm missing something. Thanks.
EDIT:
This is the code of one of my modules. When I change the vars at the top to const, the error begins. I've also defined the same imports in other modules that are interconnected.
var Datastore = require('nedb');
var validate = require("validate.js");
var path = require('path');
module.exports = class Planet{
private db_filename : string = "db/planets.db";
private ds;
private static instance : Planet = null;
private constructor(){
}
init(db_filename : string) : Planet{
this.ds = new Datastore({ filename: db_filename, autoload: true, timestampData: true });
return this;
}
static get_instance() : Planet{
if(this.instance == null)
this.instance = new Planet();
return this.instance;
}
}
Generally speaking: You can redefine a variable defined with var, you cannot with const/let-defined variables. You should always use const because it throws you errors (as you see) if you accidentally redefine a variable. If you need to modify the variable later on you have to step down to let.
// works
var a = 1;
var a = 2;
// error (because var a is defined above)
let a = 1;
let b = 1;
// error (because let b is defined above)
let b = 2;
// error
const b = 1;
// error
const a = 1;
const c = 1;
// error
const c = 2;
// error
c = 2;
I do not know why your typescript-compiler throws an error. Testing this with plain node.js it works perfectly fine.

Nodejs:Instance of modules

I understand requiring modules and what not but I would like to have instances of the module to use, kind of like an instance of a class for a java project or whatever. I have this code in my app.js:
var number = require("./number.js");
var numbers = [number.setNumber(2),
number.setNumber(3),
.....];
I have inside the number.js:
var number = -1;
exports.setNumber(num){
number = num;
}
exports.getNumber(){
return number;
}
I hope that it is sort of clear what I'm trying to do here, but I either can't find anywhere that it is explained on google, or I'm not sure what question to ask...so I hope this isn't a duplicate.
QUESTION: How do I create instances of modules/Can I create instances of modules?
Answering myself because although the answers given helped they were incomplete.
I created what seems like a javascript class similar to an answer already given that has a constructor and all other "class methods" as prototypes. Key piece though was to export it.
var myNumber = function(num) {
this.num = num
}
myNumber.prototype.setNumber = function(num) {
this.num = num
}
myNumber.prototype.getNumber = function() {
return this.num
}
module.exports = myNumber
Then, in the node its being required in I have:
var myNumber = require('./number.js');
var numbers = [ new myNumber(2),
new myNumber(3),
new myNumber(3),
new myNumber(4),
new myNumber(4),
new myNumber(5),
new myNumber(5),
new myNumber(6),
new myNumber(6),
new myNumber(8),
new myNumber(8),
new myNumber(9),
new myNumber(9),
new myNumber(10),
new myNumber(10),
new myNumber(11),
new myNumber(11),
new myNumber(12)];
This is what gives me the 20 or so different myNumber objects I was looking for. I don't know if I'm using the module.exports = myNumber correctly, but it works.
Modules are just a way to organize your code. The object, or another type, that you export from module by module.exports = is the thing, that you requiring with require
So you want something like Java Class, you can create a constructor
var Number = function(num) {
this.num = num
}
Number.prototype.setNumber = function(num) {
this.num = num
}
Number.prototype.getNumber = function() {
return this.num
}
and in your other modules you can create a new instance of Number with new keyword
var Number = require('./number.js')
var myNum = new Number(3)
myNum.setNumber(4);
// ... so on

node.js instantiate class multiple times

I have a class file that creates socket connections based on the parameter passed in during instantiate.
When I try to instantiate this file multiple times (for loop) it looks like the node.js is handling it like singleton.
Is there a way I can create new instances from a same js file that can hold its own arguments passed?
app.js
for(var i....){
require('./controller/sockets')(param[i]);
}
./controller/sockets
var util = require('util');
var param
Socket = function(iParam) {
param = iParam;
};
util.inherits(Socket,EventEmitter);
Socket.prototype.test = function(){
return param;
};
module.exports = Socket;
Thank you!
Your constructor doesn't actually create anything. All it does it store an argument in a variable. So, when you call it N times, that's all it does is store a different value into the same variable N times in a row.
Your code is essentially doing this:
var param;
var Socket = function(iParam) {
param = iParam;
}
for(var i....){
Socket(param[i]);
}
It is not clear to me what you want it to do, but perhaps the constructor needs to create an object (probably using new), initialize it and then return it.
If you want a new Socket object back from each call to the constructor, then you can do it like this:
var util = require('util');
function Socket(iParam) {
this.param = iParam;
}
util.inherits(Socket,EventEmitter);
Socket.prototype.test = function(){
return this.param;
};
module.exports = function(x) {
return new Socket(x);
};

How can a module in node.js maintain state?

I have two different js files that use the same module.
file1.js:
var mod1 = require('commonmodule.js');
mod1.init('one');
file2.js:
var mod2 = require('commonmodule.js');
mod2.init('two');
(both these files file1.js, file2.js are loaded inside my server.js file, they themselves are modules)
now in commonmodule.js:
var savedName;
exports.init = function(name)
{
savedName = name;
}
exports.getName = function()
{
return savedName;
}
I noticed that this savedName is always overridden dependent on who set it last.So it doesn't seem to work. How would I get a module to maintain state?
Note: I also tried to set savedName as exports.savedName in the commonmodule.js but it doesn't work either
You can just create a new instance every time the module is required:
commonmodule.js
function CommonModule() {
var savedName;
return {
init: function(name) {
savedName = name;
},
getName: function() {
return savedName;
}
};
}
module.exports = CommonModule;
file1.js
var mod1 = new require('./commonmodule')();
mod1.init('one');
console.log(mod1.getName()); // one
file2.js
var mod2 = new require('./commonmodule')()
mod2.init('two');
console.log(mod2.getName()); // two
modules in and of themselves are simple object instances. A single instance will be shared by all other modules (with the caveat that it is loaded via the same path). If you want state, use a class and export a constructor function.
example:
//Person.js
function Person(name) {
this.name = name;
}
module.exports = Person;
To use it:
var Person = require("./Person");
var bob = new Person("Bob");
Modules are not like classes/class functions; by default, mod1 and mod2 will refer to the same module due to caching. To keep track of per-instance state, you'll need a constructor function or something similar inside your module, e.g.
var mod = require('commonmodule.js');
var state = new mod.init('one');
Where init defines the stateful object. You could also have it return an object literal, in which case you wouldn't have to use new (e.g. var state = require('commonmodule.js').init('one');)
(This is assuming you want the module to have other, shared state in addition to the per-instance state; if that is not the case, Peter Lyons' method would be simpler.)
You could perhaps remove from cache your module. Like that:
file1.js:
var mod1 = require('commonmodule.js');
mod1.init('one');
file2.js:
delete require.cache[require.resolve(modulename)];
var mod2 = require('commonmodule.js');
mod2.init('two');
But I don't find it very convenient and clean.
But you could also clone it or make a small proxy.
Also you could create classes:
var savedName;
exports.obj = {}
exports.obj.prototype.init = function(name)
{
savedName = name;
}
exports.obj.prototype.getName = function()
{
return savedName;
}
Then :
var mod2 = new (require('commonmodule.js'))();
mod2.init('two');

Categories

Resources