Is a Node.js module a singleton? - javascript

I used to implement singleton this way:
class MySomething {
constructor(props) {}
}
let myInstance = null;
module.exports = (props) => {
//first time call
if(props) {
myInstance = new MySomething (props);
return myInstance;
} else {
return myInstance;
}
this assumes that at app.js (entry file) I will call first:
require('./MySomething')(props)
then everywhere in the project I use:
const instanceOfSomething = require('./MySomething')();
I discovered that every time I got a new instance!
What's wrong in my code?
I tried also this way:
class MySomething {...}
const mySomething = (function() {
let myInstance = null;
return {
init: function() {
myInstance = new MySomething();
},
getInstance: function() {
return myInstance ;
}
}
})();
module.exports = mySomething;
and I got the some problem when importing this module from different files, anyone can explain to me?
every require of file create new instance of mySomething
UPDATE
I tried this example now:
class MySomething {...}
const mySomething = {
myInstance: null,
init: function() {
myInstance = new MySomething();
},
getInstance: function() {
return myInstance ;
}
}
};
module.exports = mySomething;
The same problem happened, maybe it is related to my project structure, I will explain it here:
the code below belongs to module "facts"
facts folder contains a folder named "dao" this folder contains MySomething.js (the singleton)
in the facts/index.js I have:
const Localstorage = require('./dao/MySomething');
exports.init = (path) => {
Localstorage.init(path)
}
exports.Localstorage = Localstorage;
Now in a folder named "core" which contains the "facts" folder I re-exported the Localstorage again in "index.js" like this:
const facstModule = require('./facts');
exports.Localstorage = facstModule.Localstorage;
Then in "schedule" folder which contains "Runtime.js" within I write:
const { Localstorage } = require('../core');
setTimeout(() => {
const localstorageIns = Localstorage.getInstance(); //this is always null!
}, 5000)
In app.js file (entry point) I did:
const facts = require('./src/facts');
facts.init(__dirname);
Normally instance will be created before the timeout execute the callaback,
But I noticed that there two instance of Localstorage which is singleton

the cleanest way to do a singleton is
class MyClass () { ... }
module.exports = new MyClass()
if you need a singleton that gets instantiated once, I would do:
class MyClass () { ... }
let myClass
const MyClassSingleton = (...args) => {
if (myClass) {
return myClass
}
myClass = new MyClass(...args)
return myClass
}
module.exports = MyClassSingleton

Every require of file create new instance of mySomething because every time you return new object with init method and getInstance method.
If you need singleton you need do like this:
class MySomething {
constructor() {
if (!MySomething.instance) {
MySomething.instance = this;
}
}
getInstance: function() {
return MySomething.instance;
}
}
module.exports = MySomething;

class Singleton {
constructor() {
this.my_obj;
}
static makeObject() {
if (!this.my_obj) {
this.my_obj = new Singleton();
}
return this.my_obj;
}
add() {
return 1
}
}
// so to get the object we need to call the makeobject method
const obj = Singleton.makeObject()
console.log(obj.add());

Related

Is there a better way to implement a singleton pattern, using Node.js?

I'm working on a (pseudo) game engine to be used with Foundry.js. The intention was to create a scaffolding that can be reused to quickly create different game systems. To make the final product easier to read and troubleshoot, I decided to use Node.js and a very modular system. (I'm not sure if any more context is needed, but please ask if it is.)
Is there any obvious issue with my implementation?
Note: I'm an 2nd year medical student and self-taught over the past summer --> a lot of what I do might look weird so...
Note: the file and object names were removed, along with extemporaneous code. I added some fillers so that the general idea would still be conveyed
core file: singleton which contains all engine modules within its instance
const Module_A = requires('./modules/module_a.js');
const Module_B = requires('./modules/module_b.js')
module.exports = (function(){
var instance;
function createInstance(){
var o = Object.create({
Module_A: Module_A,
Module_B: Module_B,
// etc.
})
return o;
}
return {
getInstance: function(){
if(!instance){
instance = createInstance();
}
return instance;
},
Module_A: function(){
if(!instance){
instance = createInstance();
}
return instance.Module_A;
},
Module_B: function(){
if(!instan ce){
instance = createInstance();
}
return instance.Module_B;
}
};
}())
an abstract class declaration
module.exports = (
class {
constructor(){}
static getType = function(){
return entityConfig.type;
};
static entityConfig = {
type: 'Object.(Engine.Entity)'
}
}
);
a concrete class declaration
const Entity = requires('*./entity.js');
module.exports = (
class extends Entity {
static requiredParameters = () => {throw `incomplete code at ${new Error().lineNumber}`};
static optionalParameters = () => {throw `incomplete code at ${new Error().lineNumber}`};
static docData = () => {throw `incomplete code at ${new Error().lineNumber}`};
/* ------------------------------------ */
/* CONSTRUCTOR */
/* ------------------------------------ */
constructor(){
arguments.forEach(arg => {
if(!arg.includes(requiredParameters) && !arg.includes(optionalParameters)){
throw console.error(`ERROR: unknown token; ${arg}\n${docData}`);
}
});
this._data = args.data;
this.data = this._data;
}
}
);

Nodejs module extends with other module

Hi i have parent module like this.
// usermgmt.js
var usermgmt = function () {};
usermgmt.prototype.test = function () {
return "test";
};
usermgmt.private = function () {
return "private";
};
module.exports = new usermgmt();
and a Child prototype class like this.
// authentication.js
var usermgmt = require('./usermgmt');
var authentication = function () {};
authentication.prototype.callParent = function () {
usermgmt.private();
};
module.exports = new authentication();
How i implement inheritance? I searched by google but no solution works for me.
Here's a typical way to export a base class and then import it and inherit from it using the more modern syntax:
// a.js
class A {
constructor() {
}
testA() {
return "testA";
}
}
module.exports = A;
Then, in a separate file:
// b.js
const A = require('./a.js');
class B extends A {
constructor() {
super();
}
testB() {
return "testB";
}
}
let x = new B();
x.testA(); // "testA" - this is inherited obviously
x.testB(); // "testB"
As #jfriend00 said, I write these functions with class keyword which is a syntactic sugar for your code!
usermgmt.js
// usermgmt.js
class usermgmt {
constructor() {
}
test() {
return "test";
}
private() {
return "private";
}
}
module.exports = usermgmt;
Write authentication like this.
authentication.js
// authentication.js
var Usermgmt = require('./usermgmt.js');
class authentication extends Usermgmt {
constructor() {
super();
}
callParent() {
console.log(this.private());
}
authFunction() {
console.log(':: authFunction ::');
this.callParent();
}
}
module.exports = authentication;
And usage for authentication will be:
var Authentication = require('./authentication.js');
let auth = new Authentication();
auth.callParent();
auth.authFunction();
console.log(auth.test());
1) Use class and extends syntax which is easier.
2) Return Class and not its instance

Require resolves undefined

I have the following class structure.
EmployeeService.js
const {EmployeeRequestExecutor} = require('./EmployeeRequestExecutor');
class EmployeeService {
fulfill(request){
EmployeeRequestExecutor.delegateEmployeeRequest(request);
}
}
module.exports = {EmployeeService};
EmployeeRequestExecutor.js
const {HelpfulEmployee} = require('./HelpfulEmployee');
class EmployeeRequestExecutor {
static delegateEmployeeRequest(request){
let employee = new HelpfulEmployee();
employee.work(request);
}
static executeEmployeeRequest(request){
console.log('Executed', request);
}
}
module.exports = {EmployeeRequestExecutor};
HelpfulEmployee.js
const {EmployeeRequestExecutor} = require('./EmployeeRequestExecutor');
class HelpfulEmployee {
work(request){
EmployeeRequestExecutor.executeEmployeeRequest(request);
}
}
module.exports = {HelpfulEmployee};
If we then do
let employeeService = new EmployeeService();
employeeService.fulfill(request);
we get
TypeError: Cannot read property 'executeEmployeeRequest' of undefined in HelpfulEmployee.js:5:33
Why is it so that with such call structure EmployeeRequestExecutor inside HelpfulEmployee.js is undefined?
There is a circular dependency between HelpfulEmployee and EmployeeRequestExecutor (they both require each other).
Circular dependencies result most of the time from class design issues. To fix them, you should reconsider the flow of information between your objects.
This is an option, but there are many more:
const {HelpfulEmployee} = require('./HelpfulEmployee');
class EmployeeRequestExecutor {
static delegateEmployeeRequest(request){
let employee = new HelpfulEmployee();
let requestExecutor = new EmployeeRequestExecutor();
employee.work(request, requestExecutor);
}
executeEmployeeRequest(request){
console.log('Executed', request);
}
}
module.exports = {EmployeeRequestExecutor};
class HelpfulEmployee {
work(request, requestExecutor){
requestExecutor.executeEmployeeRequest(request);
}
}
module.exports = {HelpfulEmployee};
Without getting into the final purpose of this architecture, to remove the circular dependency #Nicolas already mentioned, one option is to instantiate and provide the employee from the service to the executor as:
const { EmployeeRequestExecutor } = require("./EmployeeRequestExecutor");
const { HelpfulEmployee } = require("./HelpfulEmployee");
class EmployeeService {
fulfill(request) {
let employee = new HelpfulEmployee();
EmployeeRequestExecutor.delegateEmployeeRequest(employee, request);
}
}
module.exports = { EmployeeService };

Calling an object in main.js from a module in Electron

I have an Electron app with 2 modules, one of them being the standard Menu. When I click a menu item, I want it to call an instantiated module's function.
The only solution I've found is to have my instantiated object being a property of the main electron.app object, which is globally available.
Here's my example:
main.js
const electron = require('electron');
const app = electron.app;
const WindowManager = require('components/WindowManager');
let windowManager = new WindowManager(); // <- I want my menu item to call a function from this object
const MainMenu = require('components/MainMenu');
let mainMenu = new MainMenu();
function initApp() {
let menuTemplate = mainMenu.getTemplate();
let menuBuilt = electron.Menu.buildFromTemplate(menuTemplate);
electron.Menu.setApplicationMenu(menuBuilt);
}
function mainTestFileOpen() {
console.log('File open test function in main.js');
}
// I'm trying to avoid doing this
app.testFileOpen = function() {
console.log('Function is part of "app" so globally accessible...');
}
// I'm trying to avoid doing this too
app.appWindowManager = new WindowManager();
// Start the app
app.on('ready', initApp);
components/WindowManager.js
class WindowManager {
constructor() {
this.doFileOpen = this.doFileOpen.bind(this);
}
doFileOpen() {
console.log('File open from WinwdowManager module');
}
}
module.exports = WindowManager;
components/MainMenu.js
const electron = require('electron');
class MainMenu {
constructor() {
this.template = [];
this.init = this.init.bind(this);
this.getTemplate = this.getTemplate.bind(this);
// Initialize
this.init();
}
getTemplate() {
return this.template;
}
init() {
this.template = [{
label: 'File',
submenu: [{
label: "Open File",
click() {
/** Calling a function in main.js does NOT work **/
mainTestFileOpen();
/** Calling an object in main.js doe NOT work **/
windowManager.doFileOpen();
/** If the function is part of "app" then it works **/
electron.app.testFileOpen();
/** If the instantiated object is part of "app" then it works **/
electron.app.appWindowManager.doFileOpen();
}
}]
}]
}
}
module.exports = MainMenu;
I think what I am not getting is the scope of click() in an Electron Menu template.
You're trying to call a function from a different module (every file in Node is its own module, which is different from the typical JS environment) without first importing the module.
It's not enough to just write a function in the main.js module:
function mainTestFileOpen() {
console.log('File open test function in main.js');
}
And expect to call it from the MainMenu.js module. You must first export it:
export function mainTestFileOpen() { ... }
Then, in MainMenu.js, you can import it at the top:
import { mainTestFileOpen } from "../main";
Same thing with windowManager. It doesn't look like you're doing anything with WindowManager from main.js, so just move the import and instantiation to MainMenu.js:
import { WindowManager } from "./WindowManager";
let windowManager = new WindowManager();
And then you'll be able to do:
windowManager.doFileOpen();
Side Note:
You do stuff like this in your constructor: this.doFileOpen = this.doFileOpen.bind(this);
There is no need for this as the only way somebody could call doFileOpen is by calling it on the windowManager instance like so: windowManager.doFileOpen(...).
The same applies to:
this.init = this.init.bind(this);
this.getTemplate = this.getTemplate.bind(this);

Converting Singleton JS objects to use ES6 classes

I'm using ES6 with the Webpack es6-transpiler per my article here: http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/
Does it make any sense to convert two Singleton objects to use ES6 Classes?
import { CHANGE_EVENT } from "../constants/Constants";
var EventEmitter = require('events').EventEmitter;
var merge = require('react/lib/merge');
var _flash = null;
var BaseStore = merge(EventEmitter.prototype, {
emitChange: function() {
this.emit(CHANGE_EVENT);
},
/**
* #param {function} callback
*/
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
/**
* #param {function} callback
*/
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getFlash: function() {
return _flash;
},
setFlash: function(flash) {
_flash = flash;
}
});
export { BaseStore };
This is file ManagerProducts.jsx that has a singleton that should extend from BaseStore.
/**
* Client side store of the manager_product resource
*/
import { BaseStore } from "./BaseStore";
import { AppDispatcher } from '../dispatcher/AppDispatcher';
import { ActionTypes } from '../constants/Constants';
import { WebAPIUtils } from '../utils/WebAPIUtils';
import { Util } from "../utils/Util";
var merge = require('react/lib/merge');
var _managerProducts = [];
var receiveAllDataError = function(action) {
console.log("receiveAllDataError %j", action);
WebAPIUtils.logAjaxError(action.xhr, action.status, action.err);
};
var ManagerProductStore = merge(BaseStore, {
getAll: function() {
return _managerProducts;
}
});
var receiveAllDataSuccess = function(action) {
_managerProducts = action.data.managerProducts;
//ManagerProductStore.setFlash({ message: "Manager Product data loaded"});
};
ManagerProductStore.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action;
if (Util.blank(action.type)) { throw `Invalid action, payload ${JSON.stringify(payload)}`; }
switch(action.type) {
case ActionTypes.RECEIVE_ALL_DATA_SUCCESS:
receiveAllDataSuccess(action);
break;
case ActionTypes.RECEIVE_ALL_DATA_ERROR:
receiveAllDataError(action);
break;
default:
return true;
}
ManagerProductStore.emitChange();
return true;
});
export { ManagerProductStore };
No. Makes no sense.
Here's a really simple example of a singleton object in es6:
let appState = {};
export default appState;
If you really want to use a class in your singleton approach, I would recommend against using "static" as it more confusing than good for a singleton at least for JS and instead return the instance of the class as a singleton like so...
class SomeClassUsedOnlyAsASingleton {
// implementation
}
export default new SomeClassUsedOnlyAsASingleton();
This way you can still use all the class things you like that JavaScript offers but it will reduce the confusion as IMO static isn't fully supported in JavaScript classes anyway as it is in typed languages such as c# or Java as it only supports static methods unless you just fake it and attach them directly to a class (at the time of this writing).
I'd argue that singletons (classes that manage their own singleton lifetime) are unnecessary in any language. That is not to say that singleton lifetime is not useful, just that I prefer that something other than the class manage the lifetime of an object, like a DI container.
That being said, the singleton pattern CAN be applied to JavaScript classes, borrowing the "SingletonEnforcer" pattern that was used in ActionScript. I can see wanting to do something like this when porting an existing code base that uses singletons into ES6.
In this case, the idea is that you make a private (via an un exposed Symbol) static singleton instance, with a public static instance getter. You then restrict the constructor to something that has access to a special singletonEnforcer symbol that is not exposed outside of the module. That way, the constructor fails if anyone other than the singleton tries to "new" it up. It would look something like this:
const singleton = Symbol();
const singletonEnforcer = Symbol()
class SingletonTest {
constructor(enforcer) {
if(enforcer != singletonEnforcer) throw "Cannot construct singleton";
}
static get instance() {
if(!this[singleton]) {
this[singleton] = new SingletonTest(singletonEnforcer);
}
return this[singleton];
}
}
export default SingletonTest
Then you can use it like any other singleton:
import SingletonTest from 'singleton-test';
const instance = SingletonTest.instance;
I had to do the same so here is a simple and direct way of doing a singleton,
curtsy to singleton-classes-in-es6
(original link http://amanvirk.me/singleton-classes-in-es6/)
let instance = null;
class Cache{
constructor() {
if(!instance){
instance = this;
}
// to test whether we have singleton or not
this.time = new Date()
return instance;
}
}
let cache = new Cache()
console.log(cache.time);
setTimeout(function(){
let cache = new Cache();
console.log(cache.time);
},4000);
Both console.log calls should print the same cache.time (Singleton)
In order to create Singleton pattern use a single instance with ES6 classes;
'use strict';
import EventEmitter from 'events';
class Single extends EventEmitter {
constructor() {
this.state = {};
}
getState() {
return this.state;
}
}
export default let single = new Single();
Update: According to #Bergi explanation, below one is not a valid argument.
This works because of (refer to Steven)
> If I understand CommonJS + the browser implementations correctly, the
> output of a module is cached, so export default new MyClass() will
> result in something that behaves as a singleton (only a single
> instance of this class will ever exist per process/client depending on
> env it's running in).
You can find an example here ES6 Singleton.
Note: This pattern is using in Flux Dispacher
Flux: www.npmjs.com/package/flux
Dispacher Example: github.com/facebook/flux/blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js#L16
Singleton class
class SingletonClass {
constructor( name = "", age = 0 ) {
if ( !this.constructor.instance ) {
this.constructor.instance = this;
this.name = name;
this.age = age;
}
return this.constructor.instance;
}
getName() {
return this.name;
}
getAge() {
return this.age;
}
}
const instanceOne = new SingletonClass( "One", 25 );
const instanceTwo = new SingletonClass( "Two", 44 );
console.log( `Name of instanceOne is "${instanceOne.getName()}"` );
console.log( `Name of instanceTwo is "${instanceTwo.getName()}"` );

Categories

Resources