JS发布订阅模式
一、直白的发布订阅例子
简单的售楼处例子:
-
售楼处是发布者
var salesOffices = { };
-
添加订阅者的方法,以一个函数代表一个订阅者
/** * 增加订阅者 * * @param {Function} fn 发送消息给订阅者的函数 */ salesOffices.listen = function (fn) { this.clientList.push(fn) }
-
发布消息的方法
salesOffices.trigger = function () { for (var i = 0; i < this.clientList.length; i++) { fn = this.clientList[i] fn.apply(this, arguments) } }
-
测试
// 添加订阅者小明 salesOffices.listen(function (price, squareMeter) { console.log('price', price) console.log('squareMeter', squareMeter) }) // 添加订阅者小红 salesOffices.listen(function (price, squareMeter){ console.log('price', price) console.log('squareMeter', squareMeter) }) salesOffices.trigger(2000000, 100) // price 2000000 // squareMeter 100 // price 2000000 // squareMeter 100
二、用户只订阅自己感兴趣的消息
-
售楼处是发布者
var salesOffices = { };
-
添加订阅者的方法,以一个函数代表一个订阅者
/** * 增加通知订阅者 * @param {Function} fn 发送消息给订阅者的函数 * @param {String} event 代表某一类消息 */ salesOffices.listen = function (event, fn) { // 如果还没有此类消息,给该类消息创建一个缓存列表 if (!this.clientList[event]) { this.clientList[event] = [] } this.clientList.push(fn) }
-
发布消息的方法
/** * 发布消息给所有订阅此消息的人 * * @param {String} event 代表某一类消息 * @param {*} message 发送的消息 */ salesOffices.trigger = function (event, message) { // 消息标签下的订阅者 var subscriberFuncs = this.clientList[event] // 如果没有此标签或消息标签下没有订阅者 if (!subscriberFuncs || subscriberFuncs.length === 0) { console.log('No subscribers') return false } // 发布消息 for (var i = 0, fn; fn = fns[i++]; ) { subscriberFuncs.apply(this, message) } }
-
测试
// 测试: // 添加订阅者小明 // 小明订阅了88平米房的信息 salesOffices.listen('squareMeter88', function(price) { console.log('price', price) }) // 添加订阅者小红 // 小明订阅了95平米房的信息 salesOffices.listen('squareMeter95', function(price) { console.log('price', price) }) // 添加订阅者小李 // 小明订阅了95平米房的信息 salesOffices.listen('squareMeter95', function(price) { console.log('price', price) }) // 发布 88 平方米房子的价格 salesOffices.trigger('squareMeter88', 2000000); // price 2000000 (通知小明) // 发布 95 平方米房子的价格 salesOffices.trigger('squareMeter95', 2000000); // price 2000000 (通知小红) // price 2000000 (通知小李) // 发布 1000 平方米房子的价格 salesOffices.trigger('squareMeter1000', 2000000); // No subscribers
三、发布订阅模式的通用实现
考虑到代码复用性,将发布—订阅的功能提取出来,放在一个单独的对象内 (Event)
-
定义发布者通用的基本属性和方法
var Event = { /** * 储存不同类消息下以及其下的订阅者 */ clientList: