I have seen the solution to this a while back, but can’t seem to find it again…
//
// A simple implementation of the subscriber pattern
//
var Subject = function()
{
this._observers = [];
};
// Here lies the problem
Subject.prototype.attach = function(observer, func)
{
this._observers.push(observer);
this._observers.push(func);
};
// And this only makes the problem worse
Subject.prototype.notify = function(pData)
{
var len = this._observers.length;
for(var i = 0; i < len; i += 2)
this._observers[i][this._observers[i + 1]](pData, this._observers[i]);
};
// Store the data related to the generic Observer
var Observer = function(pId){
this._el = pId;
};
//
// Notify and Update represent two possible functions that do different stuff
//
Observer.prototype.notify = function(pData, pThis)
{
document.getElementById(pThis._el).textContent = 'Notify: ' + pData;
};
Observer.prototype.update = function(pData, pThis)
{
document.getElementById(pThis._el).textContent = 'Update: ' + pData;
};
// In action
var server = new Subject();
var client1 = new Observer('observer_1' /* the ID to some DOM element */);
var client2 = new Observer('observer_2');
// Another manifestation of the problem I've ran into
server.attach(client1, 'notify');
server.attach(client2, 'update');
server.notify('[some data]');
My problem:
When the Subject calls all the observers it has registered, the callback that gets called is executed within the context of the Subject. In other words, when
Observer.update
is called, since it was called from within Subject, the reference to
this._el
refers to Subject._el, which doesn’t exist. My workaround is to register 2 things in my Subject: a reference to the Observer, and a string with the name of the callback within that Observer. Then, when the Subject broadcasts a notification, it calls the registered callback and sends a reference to the Observer to the Observer, which gets used as the this:
// instead of this._el (which would refers to server._el,
// do <observer_1>._el
I hope I’ve expressed my question clearly so I can get the help I need.
Thanks!
http://jsfiddle.net/UQ3Ay/1/
The gist of it is scope. When you set your call back function, you have to make sure it executes under the context of your observer:
The easiest way to do this is to use underscore.js and change the binding. You can also create your own using call() and apply().
This is probably closer to what you were looking for: http://jsfiddle.net/UQ3Ay/2/