JavaScript实现的发布/订阅(Pub/Sub)模式

更新时间:2016-06-22 09:25:26 点击次数:2237次

什么是发布/订阅模式


维基百科:

观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

<基于mvc的JavaScript的富应用开发>上给的解释:

发布/订阅模式(Pub/Sub)是一种消息模式,它有两个参与者: :发布者和订阅者。发布者向 某个信道发布一条消息,订阅者绑定这个信道,当有消息发布至信道时就会 接收到一个通知。重要的一点是,发布者和订阅者是完全解耦的,彼此并不知晓对方 的存在。两者仅仅共享一个信道名称。

理解起来很简单: 我去书报亭订了一份报纸,当他把报纸送给我了,我就去领了看.

这里,我就变成了订阅者,报亭就是发布者,当报纸送到的时候(状态发生改变,通知订阅者),我就去领了看(做一些操作)

一个发布者应该有三个主要的方法: 订阅,发布,退订.

先写订阅:

var PubSub = {};  
var eventObj = {};  
PubSub.subscribe = function(event, fn) {  
     eventObj[event] = fn;
}

再写发布:

PubSub.publish = function(event) {  
    if (eventObj[event]) 
        eventObj[event]();
} 

后写退订:

PubSub.off = function(event, fn) {  
    if (eventObj[event]) 
        eventObj[event] = null;
}

整理一下:

var PubSub = (function() {  
    var eventObj = {};
    return {
        subscribe: function(event, fn) {
            eventObj[event] = fn;
        },
        publish: function(event) {
            if (eventObj[event]) eventObj[event]();
        },
        off: function(event) {
            if (eventObj[event]) delete eventObj[event];
        }
    }
}());

测试:

PubSub.subscribe('event', function() {  
    console.log('event release');
});
PubSub.publish('event'); // 'event release' 

OK it work!!

这绝对是简单无脑的观察者模式的实现了,你以为这就完了吗?

这样..这个一个事件只能绑定一个操作,并且取消订阅把整个事件都删除掉了,这样就不是很好了,我们应该写一个支持一个事件绑定多个操作的,并且退订时是退订一个事件上的一个操作,而不是删除整个事件

改进版本


一个事件绑定多个操作,我们应该用一个数组把操作保存起来,发布时按订阅顺序执行,退订时删除对应的数组元素就好.

var PubSub = (function() {  
    var queue = {};
    var subscribe = function(event, fn) {
        if (!queue[event]) queue[event] = [];
        queue[event].push(fn);
    }
    var publish = function(event) {
        var eventQueue = queue[event],
            len = eventQueue.length;
        if (eventQueue) {
            eventQueue.forEach(function(item, index) {
                item();
            });
        }
    }
    var off = function(event, fn) {
        var eventQueue = queue[event];
        if (eventQueue) {
            queue[event] = eventQueue.filter(function(item) {
                return item !== fn;
            });
        }
    }
    return {
        subscribe: on,
        publish: emit,
        off: off
    }
}());

以上就是一个简单的观察者模式的实现了.
下面来测试一下:

function first() {  
    console.log('event a publish first');
}
PubSub.subscribe('a', first);  
PubSub.subscribe('a', function() {  
    console.log('event a publish second');
});
PubSub.publish('a'); // event a emit first, event a emit second

PubSub.off('a', first);  
PubSub.publish('a');  //event a emit second 

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!