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);
}
};