// 全局对象pubsub,具备发布主题、订阅、取消订阅的功能
var pubsub = {};
(function(myObject) {
// 存储广播主题
var topics = {};
// A topic identifier
var subUid = -1;
// Publish方法,传入主题名称,和主题需要传递的参数
myObject.publish = function( topic, args ) {
if ( !topics[topic] ) {
return false;
}
// 某个主题下的订阅者列举、统计
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
// 依次执行订阅者队列的订阅者的func方法
subscribers[len].func( topic, args );
}
return this;
};
// Subscribe方法,用于往某个主题topic队列里添加订阅者, 每个订阅者会被保存为一个对象
// 该对象包括一个uid和该订阅者自定义的函数
// @return 返回token
myObject.subscribe = function( topic, func ) {
if (!topics[topic]) {
// 检测某个主题是否存在
// 不存在则新建空数组,用于存储观察者对象
topics[topic] = [];
}
var token = ( ++subUid ).toString();
topics[topic].push({
token: token,
func: func
});
return token;
};
// Unsubscribe,取消订阅,通过全局唯一的token,遍历所有主题,找到那个token,然后从主题的数组中删除
myObject.unsubscribe = function( token ) {
for ( var m in topics ) {
if ( topics[m] ) {
for ( var i = 0, j = topics[m].length; i < j; i++ ) {
if ( topics[m][i].token === token ) {
topics[m].splice( i, 1 );
return token;
}
}
}
}
return this;
};
}( pubsub ));
// 实例
// 一个用于记录订阅者订阅主题和接收到的消息的简单记录器
var messageLogger = function ( topics, data ) {
console.log( "Logging: " + topics + ": " + data );
};
// 订阅者监听它们订阅的主题,一旦新的通知被广播时,它们会执行回调函数,比如messageLogger函数
// 向主体对象中,添加订阅主题和订阅函数
var subscription = pubsub.subscribe( "inbox/newMessage", messageLogger );
// 发布者负责向应用发布或通知,比如下面这个三个发布:
pubsub.publish( "inbox/newMessage", "hello world!" );
// or
pubsub.publish( "inbox/newMessage", ["test", "a", "b", "c"] );
// or
pubsub.publish( "inbox/newMessage", {
sender: "hello@google.com",
body: "Hey again!"
});
// 取消订阅
pubsub.unsubscribe( subscription );
// 一旦取消订阅,下面发布者发布的消息,不会被打印
pubsub.publish( "inbox/newMessage", "Hello! are you still there?" );
console