40

I plan to use the following pattern to make use of the requireJS based module to act as a singleton. Please notice that classA returns an instance of type 'classA', whereas the rest of the classes classB, classC, and main return the type of the class from the module. All of these are classes based on the MooTools Class.

The idea is to use the classA as a globally available singleton, the methods are just fillers. Any thoughts if this is an acceptable pattern to use?

Will this come back to bite me at a later stage? I haven't tried to run r.js on the project yet, so I am a bit worried, and look for some advise.

    // classA.js
    define([], function() {
        var classA = new Class({

            initialize: function (regionId) {
                // perform some Initialization.
                this.data = null;
            },

            doSomething: function(param) {
                // some thing.
                this.data = param;
            }
        };

        return new classA();
    });

    // classB.js
    define(["classA"], function(classA) {
        var classB = new Class({

            initialize: function (regionId) {
                // perform some Initialization.
            },

            doSomethingElse: function() {
                // some thing.
                classA.doSomething("Go back to Work Now!");
            }
        };

        return classB;
    });


    // classC.js
    define(["classA"], function(classA) {
        var classB = new Class({

            initialize: function (regionId) {
                // perform some Initialization.
            },

            doSomethingElse: function() {
                // some thing.
                classA.doSomething("Time to Play!");
            }
        };

        return classC;
    });


    // main.js
    define(["classA", "classB", "classC"], function(classA, classB, classC) {
        var main = new Class({

            initialize: function (regionId) {
                // perform some Initialization.
                this.b = new classB();
                this.c = new classC();
            },

            doEverything: function() {
                // some thing.
                this.b.doSomethingElse();
                classA.doSomething("Nap Time!");
            }
        };

        return main;
    });

Thanks much in advance...

Josh Schultz
  • 8,000
  • 9
  • 32
  • 39
Karthik
  • 1,006
  • 3
  • 10
  • 19
  • 1
    Found another post touching the same subject - [link][http://stackoverflow.com/questions/7708194/dependency-injection-with-requirejs] – Karthik Mar 16 '12 at 21:49

2 Answers2

38

No, I cannot think of a reason against using singletons with require.js.

Your module definition should export the singleton. The way you do it is fine, since it's a singleton you might be also able to avoid the new. I use something like

define(function (require) {
    var singleton = function () {
        return {
            ...
        };
    };
    return singleton();
});

The first require to the module will load and export it. Some other module requiring your singleton will just reuse the already exported one.

ggozad
  • 13,105
  • 3
  • 40
  • 49
  • 2
    Thanks for the answer. Yet, I am not clear about what is the benefit of avoiding "new" ? Or, May be I should ask, why is it better to avoid "new" in the above scenario? The module gets loaded only once anyway, so the *new* is performed only once!? Could you please comment? – Karthik Mar 29 '12 at 17:29
  • 4
    Well since it's a singleton, an object literal is appropriate. There is no need for constructors, prototypes and all the stuff you would need if this was not a singleon... – ggozad Mar 29 '12 at 19:35
  • that's because you got a "return {..}" in the singleton function. it replaces a new that you would need then in return new singleton. Personnally I prefer using a new. – Nadir Jan 05 '15 at 12:13
  • 2
    why don't you simply return { /* code */ } as you already have a closure in define and can put privates there? – King Friday Mar 01 '15 at 22:17
  • Web workers seem to be problematic with this pattern. I'd love to get feedback on my answer http://stackoverflow.com/a/33106065/1168342 since I'm still a JavaScript newbie. – Fuhrmanator Oct 13 '15 at 15:02
8

Will this come back to bite me at a later stage?

I started out with the pattern of the accepted answer here, but my single-page JavaScript app morphed into a main thread and a web worker because it was doing a lot of calculations and the page was not responsive.

As I moved some of the modules into the web worker, there was strange behavior. It took me a lot of time to figure it out, but I realized some of my requirejs modules (namely the singletons) were being loaded twice.

What I found out was that if a singleton module is required in the main thread and also in modules that run in a web worker, the singleton module will get loaded a second time in the web worker (and so it isn't really a singleton). One copy is in the main thread, the other in the web worker. If your singleton stores variables, you'll have two copies.

It all makes sense since the worker and main thread have separate address spaces (perhaps this is why I got a downvote?). I'm posting the answer here because someone might run into the same problem as there is no warning in requirejs.

The solution (in my case) was not to mix modules between the main and web worker thread. This can be a big design constraint that isn't necessarily a problem in environments such as Java or C#.

Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
  • Thanks for posting this follow up. I can see this taking a while to figure out without knowing ahead of time. – rorsach May 03 '16 at 16:29