Observer/Observable Example in Javascript
by spoike
HTML
<ul class="log">
<li class="head">
Log entries
</li>
</ul>
CSS
ul.log {
padding: 10px;
background-color: #efefef;
font-family: Arial, sans-serif;
}
ul.log li {
padding: 10px;
background-color: #fff;
border-top: dashed black thin;
}
ul.log li.head {
font-weight: bold;
border-top: none;
}
JavaScript
var log = function(entry) {
$log = $('ul.log');
$log.append('<li>' + entry + '</li>');
};
var observable = function(v) {
var val = v, subscribers = [];
// the observable object
var output = {
// subscribes to event
onChange : function(func) {
subscribers.push(func);
return output; // enables chaining
},
// the method that changes the observable object
// and emits the event
set : function(v) {
var i;
val = v;
for (i = 0; i < subscribers.length; i++) {
// this is hardly fault tolerant but as long
// as subscribers are functions it'll work
subscribers[i](v);
}
return output;
},
get : function() {
return val;
},
// the method emits an event with given message,
// useful when the observable is a complex
// object
emit : function(msg) {
var i;
for (i = 0; i < subscribers.length; i++) {
subscribers[i](msg, output);
}
return output;
},
// removes subscription
off : function(func) {
// idiomatic JS for removing objects in array
var index = subscribers.indexOf(func);
subscribers.splice(index, 1);
return output;
}
};
return output;
};
// The player token - a space ship
var shipComponent = {
velocity : observable(0)
};
// Gameloop Subject
var gameLoopComponent = observable(0);
// The Player UI component
var playerUi = (function(ship) {
var module = {
setVelocity: function(v) {
log("Velocity: " + v);
},
init: function() {
log("Initializing UI");
ship.velocity.onChange(module.setVelocity);
}
};
return module;
}(shipComponent));
// Velocity randomizer component. It randomizes the velocity.
// Doesn't need to be a module as it only reacts to the game loop
var velocityRandomizer = (function(ship, gameLoop) {
gameLoop.onChange(function(millis) {
var r = Math.random() / 10;
...