定义了一种一对多的关系(以发布者的一个topic为出发点,1个发布者可对应多个订阅者)。JS里的观察者模式功能通过回调来实现。
topics多个话题的对象
topic一个话题(是数组,为支持多个订阅者订阅相同topic)
publish:若有topic的话,执行相关topic回调
subscribe:约定唯一的topic和对应回调函数,返回唯一token
举个例子: 杂志社(发布者)支持个性化(订阅者确定,订阅者是发起者)订阅杂志,订阅者李明想订阅关于篮球巨星“勒布朗詹姆斯的私生活”(topic),用做自己公众号的素材(回调函数)。小刚也想订阅,出于好奇(回调函数)。订阅产生一个唯一id(token)可以区分同一topic的不同订阅者,取消订阅时可用。
注:与现实生活中不同的是,杂志社的个性化订阅服务是瞬间完成的,订阅者要,发布者就会给。
// 观察者(发布订阅模式) var pubsub = {}; (function(q){ var topics = {}, subUid = -1; // 发布方法,订阅方法执行后可执行 q.publish = function(topics, args){
//发布者不是手发者,只发布订阅过得topic if(!topics[topic]){ return false; } setTimeout(function(){ var subscribes = topics[topic], len = subscribes.length; while(len--){
// 循环执行topic对应的回调 subscribes[len].func(topic, args); } }, 0) return true; }; // 订阅方法,调用时先执行 q.subscribe = function(topic, func){ if(!topics[topic]){
//每个topic都是数组为了支持多个订阅者 topics[topic] = []; } var token = (++subUid).toString();
//把回调函数和token加到公共变量 topics[topic].push({ token: token, func: func });
//返回唯一token,用于取消订阅 return token; }; // 退订方法 q.unsubscribe = function(){ for(var m in topics){ for(var i =0, j= topics[m].length; i<j; i++){ if(topics[m][i].token === token){
//使用数组方法删除token对应的topic topics[m].splice(i, 1); return token; } } } return false; }; })(pubsub);