js观察者模式发布/订阅

实习期结束,最近回到学校开始学习node.js,node果然是强大。不过在涉及到文件操作的时候,发现要大量使用异步回掉操作。

以前在写页面的时候,从没这么多异步操作,只有在使用'setInterval'和'XMLHttpRequest'时了解了一下异步编程。这次在学习node的过程中,把异步回掉算是弄清楚了。但是在编码书写代码的时候,陷入了回调金字塔(callback hell)。使用es6Promise解决了一些问题。也看到了EventProxy模块基于事件驱动的解决方案。

在使用EventProxy的过程中,有种似曾相识的感觉。有点像观察者模式发布/订阅。首先使用数组缓存订阅者订阅的消息,当订阅者订阅消息的时候,把订阅的消息push到指定消息的队列中,当发布者发布消息的时候,我们遍历执行push到指定消息队列中的回调事件。

而订阅者不需要关心发布者什么时候发布消息。
而发布者不需要关心订阅者订阅的状态。

var observer = new Observe();
var callback = function(num) {
    console.log("event:"+num); // 输出event:2
};
// 订阅消息
observer.listen("event1", callback);
observer.listen("event2", callback);
// 移除订阅消息1
observer.remove('event1', callback);
// 发布者发布消息
observer.trigger("event1",1);
observer.trigger("event2",2);

具体代码如下:

function Observe() {
    // 缓存订阅者的消息队列
    this._list = [];
}
/**
 *
 * 订阅者订阅消息
 * @param  {string}   key 消息名
 * @param  {Function} fn  回调事件
 * @return {Null}       
 */
Observe.prototype.listen = function(key, fn) {
    if (!this._list[key]) {
        this._list[key] = [];
    }
    // 订阅消息,添加到缓存列表中
    this._list[key].push(fn);
};
/**
 * 
 * 移除订阅的消息
 * @param  {string}   key 消息名
 * @param  {Function} fn  回掉事件
 * @return {Null}       
 */
Observe.prototype.remove = function(key, fn) {
    // 获取当前key下的消息记录
    var arrFn = this._list[key];
    if (!arrFn) return false;
    // 未指定fn则删除当前key下所有的订阅消息
    if (!fn) {
        arrFn.length = 0;
    } else {
        for (var i = 0; i < arrFn.length; i++) {
            if (fn === arrFn[i]) {
                arrFn.splice(i,1);
            }
        }
    }
};
/**
 * 发布者发布消息
 * @param  {string} key 消息名
 * @param  {string | Object} 消息数据
 * @return {Null}  
 */
Observe.prototype.trigger = function() {
    // 得到key,第二个及以上的参数
    var key = Array.prototype.shift.call(arguments);
    var args = arguments;
    var arrFn = this._list[key];
    if (!arrFn || arrFn.length === 0) {
        return;
    }
    // 遍历执行当前key下面的所有消息
    for (var i = 0; i < arrFn.length; i++) {
        arrFn[i].apply(this, args);
    }
};
posted @ 2015-09-10 22:29  Aralic  阅读(1037)  评论(0编辑  收藏  举报