Skip to content

Instantly share code, notes, and snippets.

@addyosmani
Created February 11, 2012 01:02
Show Gist options
  • Save addyosmani/1794823 to your computer and use it in GitHub Desktop.
Save addyosmani/1794823 to your computer and use it in GitHub Desktop.
Mediator pattern
// Example 1
mediator.name = 'Doug';
mediator.subscribe('nameChange', function(arg){
console.log(this.name);
this.name = arg;
console.log(this.name);
});
mediator.publish('nameChange', 'Jorn');
// Example 2
var obj = { name : 'John' };
mediator.installTo(obj);
obj.subscribe('nameChange', function(arg){
console.log(this.name);
this.name = arg;
console.log(this.name);
});
obj.publish('nameChange', 'Sam');
var mediator = (function(){
var subscribe = function(channel, fn){
if(!mediator.channels[channel]) mediator.channels[channel] = [];
mediator.channels[channel].push({ context : this, callback : fn });
return this;
};
var publish = function(channel){
if(!mediator.channels[channel]) return false;
var args = Array.prototype.slice.call(arguments, 1);
for(var i = 0, l = mediator.channels[channel].length; i < l; i++){
var subscription = mediator.channels[channel][i];
subscription.callback.apply(subscription.context.args);
};
return this;
};
return {
channels : {},
publish : publish,
subscribe : subscribe,
installTo : function(obj){
obj.subscribe = subscribe;
obj.publish = publish;
}
};
}());
@timrchavez
Copy link

diff --git a/example.js b/example.js
index 2859683..3f6e4da 100644
--- a/example.js
+++ b/example.js
@@ -7,7 +7,7 @@ mediator.subscribe('nameChange', function(arg){
      console.log(this.name);
 });

-madiator.publish('nameChange', 'Jorn');
+mediator.publish('nameChange', 'Jorn');


 // Example 2

@addyosmani
Copy link
Author

@timrchavez thanks!

@arindambiswas
Copy link

Newbie to JS, Backbone and all things related but does this mean that the backbone-aura application is up for an update? Using it as a template.

@Troland
Copy link

Troland commented Aug 5, 2012

thanks for sharing.Can i ask a questin that why i copy the excatly same code then run it, in the console panel of chrome i get the message of undefined?So why?

@mambose
Copy link

mambose commented Nov 27, 2012

line 12 should read ...

subscription.callback.apply(subscription.context.args, args);

to pass the arguments to the subscribing function otherwise you get undefined

@ChrisBras
Copy link

It's actually:

subscription.callback.apply(subscription.context, args);

The context is saved with the channel for the purpose of being passed as "this" to the callback. Since subscription.context.args does not exist it will actually pass the window object as "this" to the callback. One of the pitfalls of javascript.

Even with that fix, something seems wrong.

I'm not sure, but I think the intention was to give each channel a unique context based off the mediator object at the time it was being "subscribed".

However, by assigning "this" to the context property in line 4, you are essentially linking every context to the same object. Thus, defeating the whole purpose of saving the context with each channel.

In order to make each context refer to the object at the time it was "subscribed", and not at the time it was "published", the object must be cloned at the time of subscription, using something like jQuery extend.

However, since this is a design pattern it should avoid using anything other than plain JavaScript. You would have to use a for-in loop to copy the properties to a clone object like so:

      var that = {};
      for(var property in this){
        that[property] = this[property];
      }

However, I might not be fulling grasping the idea of this pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment