JavaScript发布/订阅模式

最近开发一个微信小程序,在小程序启动时和我方的服务端建立wss长连接,并监听推送到小程序里的消息。有些消息是A页面关心的,有些消息是B页面关心的,将来可能会有C页面只关心少量消息类型。wx.onSocketMessage()方法该如何写呢?自然而然地想到发布/订阅模式。

以下代码,转载自https://segmentfault.com/a/1190000007409168

var publishSubscribeEvent = {

    /* 
     * 缓存列表
     * clientList: {
     *    key: [
     *        id: <int>,        // 唯一标识
     *        fn: null          // 存放回调函数
     *    ]
     * }
     * 
     */
    clientList: {},
    
    /* 
     * 添加订阅者(订阅函数),将订阅的类型与回调函数加入缓存列表
     * key: 消息的类型
     * id: 订阅的唯一标识
     * fn: 订阅的回调函数
     */
    listen: function(key, id, fn) {
        if(!this.clientList[key]) {            
            this.clientList[key] = []
        }
       
        this.clientList[key].push({            
            id: id,                         
            fn: fn                          
        })
    },
    
    // 发布消息(发布函数), 依次通知订阅者
    trigger: function () {
        var key = Array.prototype.shift.call(arguments),
            fns = this.clientList[key];
        
        if(!fns || fns.length == 0) {
            return false;                                   
        }
        
        for(var i = 0; i< fns.length; i++) {
             fns[i].fn.apply(this, arguments);
        }
    },
	
	remove: function(key, id) {
		var fns = this.clientList[key];
		
		if(!fns) {                // 如果key对应的消息没人订阅,直接返回
			return false;
		}
		
		if(!id) {                // 如果没传具体的唯一标识,则取消key的所有对应消息
			fns && (fns.length = 0);
		} else {
			for(var l = fns.length - 1; l >=0; l--) {
				var _id = fns[l].id;
				if(_id == id) {
					fns.splice(l, 1);    // 删除订阅者的回调函数
				}
			}
		}
    }
}

var installPublishSubscribeEvent = function(obj) {
	// 把publishSubscribeEvent的十八般武艺都传给obj
    for(var i in publishSubscribeEvent) {
        obj[i] = publishSubscribeEvent[i];
    }
}

// 测试代码
var sgArticleSystem = {};

installPublishSubscribeEvent(sgArticleSystem ); 

// 张三的订阅
sgArticleSystem.listen('articleA', 3, function(articleTitle, content) { 
    console.log('张三您在早前订阅了文章:articleA');
    console.log('现《' + articleTitle+ '》有了新动态');
    console.log('内容为:' + content);
});

sgArticleSystem.listen('articleB', 3, function(articleTitle, content) { 
    console.log('张三您在早前订阅了文章:articleB');
    console.log('现《' + articleTitle+ '》有了新动态');
    console.log('内容为:' + content);
});

// 李四的订阅
sgArticleSystem.listen('articleA', 4, function(articleTitle, content) { 
    console.log('李四您在早前订阅了文章:articleA');
    console.log('现《' + articleTitle+ '》有了新动态');
    console.log('内容为:' + content);
});
sgArticleSystem.listen('articleB', 4, function(articleTitle, content) { 
    console.log('李四您在早前订阅了文章:articleB');
    console.log('现《' + articleTitle+ '》有了新动态');
    console.log('内容为:' + content);
});

// 文章系统发布消息
sgArticleSystem.trigger('articleA', '肖申克的救赎', '梦想是关不住的');
sgArticleSystem.trigger('articleB', '勇敢的心', 'Freedom');

sgArticleSystem.remove('articleA', 3);    // 删除张三的订阅
console.log('###### 删除张三articleA对的订阅');

sgArticleSystem.trigger('articleA', '肖申克的救赎', '梦想是关不住的');
sgArticleSystem.trigger('articleB', '勇敢的心', 'Freedom');
基本功能都有了,感觉不爽的是publishSubscribeEvent是对象的写法,而不是类。

猜你喜欢

转载自blog.csdn.net/jinjiankang/article/details/80646555