Search code examples
javascriptsingletoncustom-events

How to create and event handler inside a Singleton class - Javascript


I have the next code:

// Singleton
var mySingleton = (function () {
    // Private methods and variables

    function privateMethod(){
        console.log( "I am private" );
    }

    var privateVariable = "Im also private";

   return {
      // Public methods and variables
      hello: function () {
        console.log( "I want to ''fire'' the event 'hello'" );
      }
    };
})();

And I want to create my own event handling system. I'm tried with the following code:

var mySingleton = (function () {

    function privateMethod(){
        console.log( "I am private" );
    }

    var handlers = {};
    mySingleton.prototype.registerHandler = function(event, callback) {
       this.handlers[event] = callback;
    };
    mySingleton.prototype.fire = function(event) {
       this.handlers[event]();
    };

    var privateVariable = "Im also private";

    return {
      hello: function () {
        console.log( "I want to ''fire'' the event 'hello'" );
        fire('hello');
      }
    };

})();

And I used as follows:

mySingleton .registerHandler('hello', function () {
    alert('Hi!');
});

But this doesn't work... Throw me the next error:

Cannot read property 'prototype' of undefined

Anybody can help me, please?

MY CURRENT ERROR:

Uncaught TypeError: Cannot set property 'mycustomevent' of undefined
Uncaught TypeError: Cannot read property 'mycustomevent' of undefined

Solution

  • Your code is trying to make assignments to the "prototype" property of an object that doesn't exist yet. There's really no point anyway; just put those methods in the object you're returning:

    var mySingleton = (function () {
    
        function privateMethod(){
            console.log( "I am private" );
        }
    
        var handlers = {};
        var privateVariable = "Im also private";
    
        return {
          hello: function () {
            console.log( "I want to ''fire'' the event 'hello'" );
            this.fire('hello');
          },
          registerHandler: function(event, callback) {
            handlers[event] = callback;
          },
          fire: function(event) {
            if(handlers[event]){
               handlers[event]();
            }else{
               console.error("Sorry, there aren't any handlers registered with that name");
            }
          }
        };
    })();
    

    The object you're building as "mySingleton" is just a plain object; that is, it's an instance of the Object constructor. There's no new prototype involved.

    You don't need a this reference to access the "handlers" map because it's in the closure scope of the event handling functions. The way the code is arranged, however, does require this when using the .fire() API, though that could be fixed too by having the service functions be locally declared in the anonymous wrapper.