JavaScript Event System

Lets say we are super rich and we have an butler who handles things for us. In fact, we live so leisurely that any mundane events are taken care of by our secretary/personal assistant. That would be nice. It is the same thing in JavaScript. We don't want to take care of everything that happens in one function. That leads to a sticky mess. Instead we wan't to use delegation. Yep, exactly like management - lets pass it on to someone else to do. Let's try an example with our car (yeah, original idea right?).

var car = {
  engineBroke : function () {
    console.log("Oh no! Engine broke");
  },
  dirty : function () {
    console.log("I need a valet!");
  },
  mot : function () {
    console.log("MOT due!");
  }
};

Great, we have a car. Lets say something shitty happens like a bust engine, or the MOT is due. We really don't have time for that shizzle, so lets take care of it using a decorator function to handle events. What the decorator should do is extend the target object to enable the attachment events, and then trigger those events whenever the right circumstance calls for it.

var eventSystem = function (target) {
  target.events = {};
  target.on = function (verb, cb) {
    target.events[verb] = target.events[verb] || [];
    target.events[verb].push(cb);
  }
  target.trigger = function (e) {
    var i;
    for (i = 0; i < target.events[e].length; i++) {
      target.events[e][i]();
    }
  }
};

Now call the decorator function with the object we want to extend.

eventSystem(car);

So far so good. Now is a good time to explain why we are going about things this way. Two words, "tight coupling". It sounds nice and romantic, but code is no place for romance. We want a system with high cohesion (things working together in a way that makes sense) along with loose coupling (no hard coded dependancies). A system with tight coupling is really bad practice, just leading to nightmares along the line. High cohesion indicates a well considered approach to solving the problem at hand. Our car might break down, but we may or may not have a mechanic. We cannot add a call to a mechanic to fix the car from our car. We are rich though, so we not only have a mechanic, we have a valet.

var mechanic = {
  fixEngine : function () {
    console.log("Engine fixed, £500 please!");
  },
  passMot : function () {
    console.log("Fixed car so it is legal");
  }
};

var valet = { cleanCar : function () { console.log("Shiny new car!"); } };

We also have a shitty government, so we are not really living in an ideal world:

var government = {
  processMot : function () {
    console.log("Car verified as legal");
  }
};

Thats the setup. We have some great staff. Now it is time to set them to work. All we need to do is attach events to the car, and then set the way to handle those events by use of a callback.

car.on("engineBroke", mechanic.fixEngine);
car.on("mot", mechanic.passMot);
car.on("mot", government.processMot);
car.on("dirty", valet.cleanCar);

Now any event that is triggered gets handled. Teamwork.

car.trigger("engineBroke");
car.trigger("mot");
car.trigger("dirty");

Have a fiddle