Last active
November 27, 2017 02:40
-
-
Save MrKou47/0e01ef42882cdf1c80d996fdbef9c290 to your computer and use it in GitHub Desktop.
发布/订阅模式
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function PubSub() { | |
this.eventList = []; | |
} | |
PubSub.prototype.subscrible = function (eventName, callback) { | |
const currentEvent = this.eventList.find(obj => obj && obj.name === eventName); | |
if (currentEvent) { | |
this.eventList.find(obj => obj && obj.name === eventName).callback = callback; | |
} else { | |
this.eventList.push({ name: eventName, callback, }); | |
} | |
}; | |
PubSub.prototype.publish = function (eventName, args) { | |
const currentEvent = this.eventList.find(obj => obj && obj.name === eventName); | |
if (currentEvent) currentEvent.callback(args); | |
}; | |
PubSub.prototype.unSubscrible = function (eventName) { | |
this.eventList = this.eventList.filter(eObj => eObj.name !== eventName); | |
} | |
/** | |
* 原型继承 | |
* @param {*} currentClass | |
* @param {*} targetClass | |
*/ | |
function inheritClass(currentClass = {}, targetClass) { | |
for (var name in targetClass.prototype) { | |
currentClass.prototype = Object.assign({}, targetClass.prototype, currentClass.prototype); | |
// Object.defineProperty(currentClass, name, targetClass.prototype[name]); | |
} | |
} | |
// 订阅一个事件 | |
pubSub.subscrible('start_class', function (time) { | |
console.log(`要上课啦 上课时间为 ${time}`); | |
}); | |
// // 发布一个事件 并携带参数 | |
pubSub.publish('start_class', new Date()); | |
pubSub.unSubscrible('start_class'); // 取消订阅事件 | |
pubSub.publish('start_class', new Date('2017/07/07')); // 无效 | |
function Person() { | |
PubSub.call(this); | |
} | |
inheritClass(Person, PubSub); // 让 Person 同样具有发布/订阅事件的能力 | |
const Bob = new Person(); | |
Bob.subscrible('sleep', function (when) { | |
console.log(`people want sleep!!! ${when}`); | |
}); | |
Bob.publish('sleep', 'now!!'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
如何实现一个发布订阅模型
我们的目的是,实现一个事件驱动的控制器,通过 定义事件(包括事件的名称,和触发事件后会发生什么事情)和触发事件,来控制我们代码的运行过程。 好处是: 定义一个事件,能够在任意时间触发回调函数。
举例:PandaTV 是如何实现订阅的?
比如,我在看托马斯直播,然后这个狗贼杀人之后说“大家订阅走一走”,小王听了,点了订阅, 当他点击了订阅按钮后,发送请求到pandatv服务端,服务器上维护了一个数组,那服务器接收了请求之后,调用了 subscribe 方法。比如
subscribe('tuomasi', 'xiaowang')
。那下次托马斯点击“开播”按钮的时候,他就触发了publish('tuomasi')
事件,然后服务器就向小王手机上发了短信,说托马斯开播啦。这就是一个订阅的例子。首先定义包含所有事件的数组
此数组包含了所有我们定义的事件以及事件的回调函数。
接着编写定义事件的方法 —— subscribe
那我们可以通过此方法定义事件和事件的回调,定义后将定义的事件
push
到我们刚才定义的数组中**注意: ** 如果我们在定义事件的时候,之前已经有了相同名字的事件,那我们就需要把之前我们定义的事件的回调函数替换为我们当前的、新的回调函数。
触发事件(也叫做发布事件)的方法 —— publish
我们通过此方法,提供一个事件的名称,在我们保存事件的数组
eventList
中查找我们想要触发的事件,找到后,执行此事件的回调函数。退订方法
我们通过此方法来删除
eventList
中的事件,这样我们在调用publish
方法的时候就不会触发了我们再回到之前的pandaTv的问题,大家应该发现,我们不是说
subscribe
方法只有一个回调么,那小王订阅了之后小明订阅了怎么办?实际上这个方法应该是,用户订阅,和主播开播, 这两个服务端已经写好了这两个事件。意思就是,用户触发的是一个通用的方法,比如之前服务器已经写好了
subscribe('订阅主播', function (主播名, 用户id) { 在这里方法里面,向数据库里面、此主播的订阅的观众的数组里面push小王的用户id })
,那用户点击订阅后实际上就是,比如小王的用户id是666, 那在服务器端就是触发了一个这个 ‘订阅主播’ 的事件:publish('订阅主播', '托马斯', '666')
,然后服务端同时也定义了一个开播的事件,比如subscribe('开播',function(主播名) { 在这个方法里面,服务器去找此主播的所有订阅观众,然后给每一个人都发短信 })
。这就是实现最简单的订阅的过程。