Singleton pattern with Browserify/CommonJS - javascript

Trying to implement the singleton pattern within CommonJS modules, using Browserify. So far:
// foo.js
var instance = null;
var Foo = function(){
if(instance){
return instance;
}
this.num = 0;
return instance = new Foo();
}
Foo.prototype.adder = function(){
this.num++;
};
module.exports = Foo();
// main.js
var foo = require('./foo.js');
console.log(foo.num); // should be 0
foo.adder(); // should be 1
var bar = require('./foo.js');
console.log(bar.num); // like to think it'd be 1, not 0
First problem is that I get a maximum call stack exceeded error when I load the built JS file in the browser, but secondly, am I approaching this correctly? Is this possible?

First problem is that I get a maximum call stack exceeded error
Well, that comes from your Foo function recursively calling new Foo…
but secondly, am I approaching this correctly?
No. For singletons, you don't need a "class" with a constructor and a prototype - there will only ever be one instance. Simply create one object, most easily with a literal, and return that:
module.exports = {
num: 0,
adder: function(){
this.num++;
}
};

The result of any require call is a singleton -- whether a singleton instance or a singleton function or a singleton factory function. Furthermore, a require call should be idempotent -- poorly written CommonJS modules may violate this, so if a CommonJS module has a side effect, that side effect should happen only once no matter how many times that require is called.
The code snippet you have
if(instance){
return instance;
}
// ...
return instance = new Foo();
is a legacy of the kinds of hoops you'd have to jump through if you were using plain old JavaScript to create singletons. It's totally unnecessary when using CommonJS and besides that, it leads to your maximum call stack exceeded issue.
Your code could be rewritten like this:
var Foo = function(){
this.num = 0;
}
Foo.prototype.adder = function(){
this.num++;
};
module.exports = new Foo();
or even more succinctly:
module.exports = {
num: 0,
adder: function(){ this.num++; }
}
because putting the adder method on the prototype doesn't gain you any real efficiency if you're only creating a single instance of Foo, and because you don't need to hide anything in the closure.

Related

How to reference the calling Javascript module?

I am using what I understand to be the Javascript module pattern, and jQuery.
I have an app which has a public and an admin side. Each has its own JS file, though some functionality is shared so I have extracted it to a common file. Gulp combines the common + public files into a single file for use on the public side, and the common + admin files into a single file for use on the admin side.
The public JS file includes something like:
var PublicFoo = (function () {
var bar = function() {
// ..
};
var init = function() {
$button.on('click', Common.someCommonThing);
};
return {
init: init
};
})();
The HTML page where this code is needed fires it off like so:
<script>
PublicFoo.init();
</script>
The admin JS file includes something very similar, also defining a bar() function, and calling the same Common module function.
var AdminFoo = (function () {
var bar = function() {
// ..
};
var init = function() {
$button.on('click', Common.someCommonThing);
};
return {
init: init
};
})();
The common JS file (shared and combined with both public and admin JS) includes something like:
var Common = (function () {
var someCommonThing = function() {
// Do stuff.
// When done, I want to call bar() in the calling module.
// This does not work, throws 'Uncaught ReferenceError: bar is not defined'
bar();
};
return {
someCommonThing: someCommonThing,
// ...
};
})();
From the Common module, how can I reference a function in the calling module?
I know about .caller, but apparently that is non-standard and should not be used.
I could maybe somehow pass in the name of the calling module as a parameter to Common, and reference it, but that seems ugly:
// In PublicFoo
var init = function() {
$button.on('click', function() {
Common.someCommonThing(PublicFoo)
});
};
// In Common
var someCommonThing = function(callingModule) {
// ...
callingModule.bar();
I could also of course extract the bar() call out and do it back in the calling module, but that doesn't seem so neat either:
// In PublicFoo
var init = function() {
$button.on('click', function() {
Common.someCommonThing();
bar();
});
};
// ... and the same thing in AdminFoo
I feel like this must be JS modules 101, a basic requirement, and yet I can't seem to find anything about it, though I may be searching using the wrong terminology. Or is the reason I can't find how to do this because it should not be done this way?
How can I reference the appropriate bar() from the Common module?
I know about .caller, but apparently that is non-standard and should not be used.
Also it doesn't work in your case, as the caller is the event handler and neither PublicFoo nor AdminFoo.
I could maybe somehow pass in the name of the calling module as a parameter to Common, and reference it
Yes, passing references to the thing that you want to be called is the way to go if you want someCommonThing to do different things after it has finished. Notice you really should only use such a callback when the thing is asynchronous, otherwise just returning and calling bar afterwards (like in your last snippet) is much easier.
How can I reference the appropriate bar() from the Common module?
If both bars might be loaded at once into the page, then there's no way around a parameter that references the callback.
However, that doesn't seem to be the case in your example - on one page, AdminFoo takes the role of Foo and on the other page PublicFoo takes the role of Foo.
So just reference only Foo.bar from Common! Let the respective pages fill it with the appropriate value, i.e.
var Foo = AdminFoo
on the admin page and
var Foo = PublicFoo
on the public page.
Passing functions to other functions is very common and perfectly idiomatic JavaScript, so you could do it like this:
// In PublicFoo
var bar = function() {
// ..
};
var init = function() {
$button.on('click', function() {
Common.someCommonThing(bar)
});
};
// In Common
var someCommonThing = function(bar) {
// ...
bar();
};

Using this or new in JS?

I've got 3 codes :
var control = new Control();
function Control() {
this.doSomethingElse = function() {...}
this.doSomething = function () {
control.doSomethingElse();
}
}
Or
var control = new Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
}
Or
var control = Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
return self;
}
Important : The function is a controller, and just declared once. Then I'm using "control" everywhere in my code...
I was wondering if the control.doSomethingElse() was slow ?
In the end, what is the right thing to do and/or the fastest code in those exemple ?
Thanks !
The first is wrong - an object should never internally use the variable name by which it is known outside. Other code could change that variable to point to something else, breaking this code.
The third is also wrong - when calling Control() without new the assignments to this.foo inside will end up getting attached to the global object (except in strict mode, where there's no implicit this on bare function calls, so the assignment to this.doSomethingElse tries to attach to undefined, causing a runtime error).
That only leaves the second as appropriate, but ultimately it's a question of correctness, not performance.
Do not define methods in constructor - that means defining them every time an instance is created. Use Control.prototype.foo = function() {} instead. Also you do not need to return this if you're using new operator - that's the whole point of new operator.
The recommended approach is this:
function MyClass(param1) {
// Here we're changing the specific instance of an object
this.property1 = param1;
}
// Prototype will be shared with all instances of the object
// any modifications to prototype WILL be shared by all instances
MyClass.prototype.printProperty1 = function() {
console.log(this.property1);
}
var instance = new MyClass("Hello world!");
instance.printProperty1(); // Prints hello world
To understand this code, you need to understand javascript's prototype-based inheritance model. When you create instance of MyClass, you get a new object that inherits any properties present in MyClass.prototype. Read more about it.
Also I wonder:
The function is a controller, and just declared once.
If you're not using this multiple times, you don't need to create something like class. You can do this instead:
var control = {doSomething:function() { ... }};
I assume you are used to Java, where everything must be a class, whether it makes sense or not. Javascript is different, you can also make single objects or functions as you need.

Node.js singleton module pattern that requires external inputs

normally we might create a simple singleton object like so with Node.js:
var foo = {};
module.exports = foo;
or
function Foo(){}
module.exports = new Foo();
however
what is the best way to make a clean singleton module that needs an external variable for initialization? I end up making something like this:
var value = null;
function init(val){
if(value === null){
value = val;
}
return value;
}
module.exports = init;
this way someone using the module can pass in an initializing value for a certain variable. Another way to do it would be like so:
function Baz(value){
this.value = value;
}
var instance = null;
module.exports = function init(value){
if(instance === null){
instance = new Baz(value);
}
return instance;
}
there's two problems I encounter with this:
(1) this is minor, but the semantics is wrong. We can rename init to getInstance, but we can't make the same function literal mean "initialize and get" since they are different meanings. So we have to have a function that does two different things. Create an instance and retrieve and instance. I don't like this especially since in some cases we need to make sure the argument to initialize the instance is not null. With multiple developers using a module it's not clear if a module has been initialized yet, and if they pass in undefined into the module that hasn't been initialized, that could become a problem or just confusing at the least.
(2) this is more important - in some cases initializing Baz is asynchronous. For example, making a Redis connection or reading from a file to initialize a singleton, or making a socket.io connection. This is what really trips me up.
e.g. here is a module that I have that I consider really ugly that stores a socket.io connection:
var io = null;
var init = function ($io) {
if (io === null) {
io = $io;
io.on('connection', function (socket) {
socket.on('disconnect', function () {
});
});
}
return io;
};
module.exports = {
getSocketIOConn: init
};
the above module is initialized like so:
var server = http.createServer(app);
var io = socketio.listen(server);
require('../controllers/socketio.js').getSocketIOConn(io);
So I am looking for a design pattern that allows us to create a singleton module where the initialization process is asynchronous. Ideally we won't have the same function both initializing the instance as well as retrieving it. Does such a thing exist?
I don't think there is necessarily a way to create a pattern that solves this problem but perhaps I am making the mistake of structuring my code in a way that is creating a problem that doesn't need to exist- the problem of initializing a module with a value only once, but using one function to both init the instance and retrieve the instance.
It sounds like you're trying to create a module that gets initialized in one place and then uses some shared resource from that initialization for other users of that module. That is a semi-common need in the real world.
First off, it's ideal if a module can load or create the things that it depends on because that makes it more modular and useful on its own and puts less of a burden on someone using it. So, in your case, if your module could just create/load the thing that it needs when the module is first created and just store that resource in it's own module variable, then that would be the ideal case. But, that is not always possible because the shared resource may be someone else's responsibility to set up and initialize and this module just needs to be made aware of that.
So, the common way to do that is to just use a constructor function for the module. In Javascript, you can allow the constructor to take an optional argument that provides the initialization info. The code responsible for setting up the module would call the constructor with the desired setup parameter. Other users of the module that weren't responsible for setting up the module could just either not call the constructor or if they want a return value or there are other constructor parameters that they should pass, they could pass null for that setup parameter.
For example, you could do this:
var io;
module.exports = function(setup_io) {
if (setup_io) {
io = setup_io;
}
return module.exports;
};
module.exports.method1 = function() {
if (!io) {
throw new Error("Can't use method1 until io is properly initalized");
}
// code here for method1
};
// other methods here
Then, users of the module could either do this:
// load myModule and initialize it with a shared variable
var myModule = require('myModule')(io);
or this:
// load myModule without initializing it
// (assume some other module will initialize it properly)
var myModule = require('myModule');
Note: For developer sanity, it would be useful to have individual methods that require appropriate setup (before they can be used properly) to check to see if the module has been setup when any method is called that needs that setup in order to properly inform a developer that they have called a method before setting up the module properly. Otherwise, errors can happen much further downstream and likely won't have useful error messages.
If you now want the initialization process to be async, that can be done too, but it certainly complicates other uses of the module because they won't necessarily know when/if the module has been initialized.
var moduleData;
var readyList = new EventEmitter();
module.exports = function(arg, callback) {
// do some async operation here involving arg
// when that operation completes, you stored the result
// in local module data and call the callback
readyList.on("ready", callback);
someAsyncOperation(arg, function() {
// set moduleData here
// notify everyone else that the module is now ready
readyList.emit("ready");
// remove all listeners since this is a one-shot event
readyList.removeAllListeners("ready");
});
return module.exports;
};
If you have other users of this module that wish to be notified when it has finished initializing, you can allow them to register a callback themselves to be notified when the module is ready.
// pass a callback to this method that will be called
// async when the module is ready
module.exports.ready = function(fn) {
// if module already ready, then schedule the callback immediately
if (moduleData) {
setImmediate(fn);
} else {
readyList.on("ready", fn);
}
};
If, for reasons I don't quite understand, you want to use the same constructor for both initialization and ready detection, that can be done, though I don't think it's near as clear as just using a separate method for ready detection:
var moduleData;
var readyList = new EventEmitter();
module.exports = function(arg, callback) {
// if both arguments passed, assume this is a request for module
// initialization
if (arguments.length === 2) {
// do some async operation here involving arg
// when that operation completes, you stored the result
// in local module data and call the callback
readyList.on("ready", callback);
someAsyncOperation(arg, function() {
// set moduleData here
// notify everyone else that the module is now ready
readyList.emit("ready");
// remove all listeners since this is a one-shot event
readyList.removeAllListeners("ready");
});
} else {
// constructor called just for a ready request
// arg is the callback
if (moduleData) {
// if module already ready, then schedule the callback immediately
setImmediate(arg);
} else {
// otherwise, save the callback
readyList.on("ready", arg);
}
}
return module.exports;
};
Usage for async initializing the module:
// async initialization form
var myModule = require("myModule")(someArg, function() {
// can use myModule here
});
Usage for loading the module and getting notified when someone else has initialized it:
var myModule = require("myModule")(function() {
// can use myModule here
});

What's the different between 'new' and not 'new' instance when using RequireJs?

I'm wondering what's the different between new module and not new module when using RequireJs. What's the different? and which one should I use. For example I have this module
define('somemodule', [], function() {
var module = function() {
var method = function() {
return "something";
}
return {
method : method
};
};
return module;
});
// Use the module (import)
require(['somemodule'], function(somemodule){
console.log(new somemodule().method());
console.log(somemodule().method());
});
http://jsfiddle.net/noppanit/fpT9K/1/
In your example, it does not matter, if you call somemodule with or without new!
Why?
Because your contructor returns a new object and does not make use of this.
But if we translate your example as followed..
var module = function() {
var method = function() {
return "something";
}
this.method = method;
};
.. it works the same. Now if you call module with new, the tiny this refers to a new scope. Because new creates a new scope for your constructor.
Because of that you can use your module like this:
var myInstance = new module();
myInstance.method(); // will output "something"
But now, if you call module without new, the this will refer to the global scope, which is the window object in a browser.
var myInstance = module();
myInstance.method(); // will cause an error
method(); // will output "something" which is not what you wanted.
So?
The new prefix makes sure, your module gets it's own scope. But as I said, your example with module returning an object and not using this, it does'nt matter either you use new or not.
How to prevent functions from being called without new?
Stick to widely used naming conventions: constructors are Capitalized.
And in bigger projects you should test if the constructor function is called with new:
var Module = function() {
// simply check if "this" is an instance of "module"
if (! (this instanceof Module)) {
// and if not, call "module" again, with the "new" prefix
return new Module();
}
var method = function() {
return "something";
}
this.method = method;
};
Just as with any other function, calling via new instantiates a new object for the value of this in the function. When you call it without new, as in the second call, the value of this will be that object returned from the main module function.
As to which you should use, that depends on what "method" expects to be able to do with this. It might not matter at all, or it might matter a lot; it depends on the actual code and the design of your system.

Creating a Javascript Object Which Does Nothing

As a somewhat hacky method of disabling functionality, I came up with the idea of using some javascript like this:
//fakefrob.js
var frob = function () {
return {
myFunc: function(){},
myFunc1: function(){},
myFunc2: function(){return 2;},
myFunc3: function(){},
myFunc4: function(){}
};
}();
In this example, the real frob has implementations of these functions. Obviously this is a hack (the functions mostly do nothing or have placeholder return values). If I add foobar to realfrob.js, I must add an empty implementation of foobar to fakefrob.js. Is there a way (ideally without using a library) to write fakefrob.js such that frob.foobar acts like foobar was defined as function(){};, without actually adding foobar to fakefrob.js?
Is there a way (ideally without using a library) to write fakefrob.js such that frob.foobar acts like foobar was defined as function(){};, without actually adding foobar to fakefrob.js?
You mean, a catch-all property, mapped to a no-op function? No, JavaScript doesn't (currently) have catch-all properties at all. (I believe some mechanism for them is being considered, as part of the proxy stuff coming down the pike at some stage.)
If you have access to the real frob in your code, though, your fakefrob can be generated completely automatically:
// Assumes `frob` already exists
(function() {
var mock;
var name;
// Build the mock, with a function for each function
// on the real object.
mock = {};
for (name in frob) {
if (typeof frob[name] === "function") {
mock[name] = function() { };
}
}
// Replace the original
frob = mock;
})();
And of course, if you wanted to copy the non-function properties, you could do that at the same time.
Note that I intentionally did not include hasOwnProperty in the loop above, as I assume you want your mock to include functions even if frob inherits them from a prototype.
If frob inherits some functions and you wanted your mock to exhibit the same hasOwnPropety behavior for them as the original frob, you can get more creative:
// Assumes `frob` already exists
(function() {
var mock;
var mockProto;
var name;
function FakeFrob() {
}
mockProto = FakeFrob.prototype;
// Build the mock, with a function for each function
// on the real object.
mock = new FakeFrob();
for (name in frob) {
if (typeof frob[name] === "function") {
if (frob.hasOwnProperty(name)) {
mock[name] = function() { };
}
else {
mockProto[name] = function() { };
}
}
}
// Replace the original
frob = mock;
})();
Now, if the original frob had its own foo (frob.hasOwnProperty("foo") is true) but an inherited bar (frob.hasOwnProperty("bar") is false), hasOwnProperty on your mock would say exactly the same thing.
As T.J. Crowder suggests, supported browsers can use a proxy object to accomplish this:
var frob = new Proxy({}, {get: function(){return function(){}}})
How this works:
This creates a proxy which intercepts all property getters, replacing the result with an empty function. Normally, a proxy object is used to to intercept and eventually forward calls to our target (here, the target is {}). However, this code blindly returning an empty function, completely ignoring the target.

Categories

Resources